diff options
Diffstat (limited to 'lib/mesa')
135 files changed, 35130 insertions, 750 deletions
diff --git a/lib/mesa/src/amd/common/ac_shader_abi.h b/lib/mesa/src/amd/common/ac_shader_abi.h new file mode 100644 index 000000000..b04dc076d --- /dev/null +++ b/lib/mesa/src/amd/common/ac_shader_abi.h @@ -0,0 +1,101 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * 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 AC_SHADER_ABI_H +#define AC_SHADER_ABI_H + +#include <llvm-c/Core.h> + +enum ac_descriptor_type { + AC_DESC_IMAGE, + AC_DESC_FMASK, + AC_DESC_SAMPLER, + AC_DESC_BUFFER, +}; + +/* Document the shader ABI during compilation. This is what allows radeonsi and + * radv to share a compiler backend. + */ +struct ac_shader_abi { + LLVMValueRef base_vertex; + LLVMValueRef start_instance; + LLVMValueRef draw_id; + LLVMValueRef vertex_id; + LLVMValueRef instance_id; + LLVMValueRef frag_pos[4]; + LLVMValueRef front_face; + LLVMValueRef ancillary; + LLVMValueRef sample_coverage; + + /* For VS and PS: pre-loaded shader inputs. + * + * Currently only used for NIR shaders; indexed by variables' + * driver_location. + */ + LLVMValueRef *inputs; + + void (*emit_outputs)(struct ac_shader_abi *abi, + unsigned max_outputs, + LLVMValueRef *addrs); + + LLVMValueRef (*load_ubo)(struct ac_shader_abi *abi, LLVMValueRef index); + + /** + * Load the descriptor for the given buffer. + * + * \param buffer the buffer as presented in NIR: this is the descriptor + * in Vulkan, and the buffer index in OpenGL/Gallium + * \param write whether buffer contents will be written + */ + LLVMValueRef (*load_ssbo)(struct ac_shader_abi *abi, + LLVMValueRef buffer, bool write); + + /** + * Load a descriptor associated to a sampler. + * + * \param descriptor_set the descriptor set index (only for Vulkan) + * \param base_index the base index of the sampler variable + * \param constant_index constant part of an array index (or 0, if the + * sampler variable is not an array) + * \param index non-constant part of an array index (may be NULL) + * \param desc_type the type of descriptor to load + * \param image whether the descriptor is loaded for an image operation + */ + LLVMValueRef (*load_sampler_desc)(struct ac_shader_abi *abi, + unsigned descriptor_set, + unsigned base_index, + unsigned constant_index, + LLVMValueRef index, + enum ac_descriptor_type desc_type, + bool image, bool write); + + /* Whether to clamp the shadow reference value to [0,1]on VI. Radeonsi currently + * uses it due to promoting D16 to D32, but radv needs it off. */ + bool clamp_shadow_reference; + + /* Whether to workaround GFX9 ignoring the stride for the buffer size if IDXEN=0 + * and LLVM optimizes an indexed load with constant index to IDXEN=0. */ + bool gfx9_stride_size_workaround; +}; + +#endif /* AC_SHADER_ABI_H */ diff --git a/lib/mesa/src/amd/vulkan/dev_icd.json.in b/lib/mesa/src/amd/vulkan/dev_icd.json.in index f726df02a..cc80641f5 100644 --- a/lib/mesa/src/amd/vulkan/dev_icd.json.in +++ b/lib/mesa/src/amd/vulkan/dev_icd.json.in @@ -1,7 +1,7 @@ { "file_format_version": "1.0.0", "ICD": { - "library_path": "@build_libdir@/libvulkan_radeon.so", + "library_path": "@libvulkan_radeon_path@", "api_version": "1.0.3" } } diff --git a/lib/mesa/src/amd/vulkan/radv_debug.c b/lib/mesa/src/amd/vulkan/radv_debug.c new file mode 100644 index 000000000..b69c05b64 --- /dev/null +++ b/lib/mesa/src/amd/vulkan/radv_debug.c @@ -0,0 +1,736 @@ +/* + * Copyright © 2016 Red Hat. + * Copyright © 2016 Bas Nieuwenhuizen + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <sys/utsname.h> + +#include "sid.h" +#include "gfx9d.h" +#include "ac_debug.h" +#include "radv_debug.h" +#include "radv_shader.h" + +#define TRACE_BO_SIZE 4096 + +#define COLOR_RESET "\033[0m" +#define COLOR_RED "\033[31m" +#define COLOR_GREEN "\033[1;32m" +#define COLOR_YELLOW "\033[1;33m" +#define COLOR_CYAN "\033[1;36m" + +/* Trace BO layout (offsets are 4 bytes): + * + * [0]: primary trace ID + * [1]: secondary trace ID + * [2-3]: 64-bit GFX pipeline pointer + * [4-5]: 64-bit COMPUTE pipeline pointer + * [6-7]: 64-bit descriptor set #0 pointer + * ... + * [68-69]: 64-bit descriptor set #31 pointer + */ + +bool +radv_init_trace(struct radv_device *device) +{ + struct radeon_winsys *ws = device->ws; + + device->trace_bo = ws->buffer_create(ws, TRACE_BO_SIZE, 8, + RADEON_DOMAIN_VRAM, + RADEON_FLAG_CPU_ACCESS); + if (!device->trace_bo) + return false; + + device->trace_id_ptr = ws->buffer_map(device->trace_bo); + if (!device->trace_id_ptr) + return false; + + memset(device->trace_id_ptr, 0, TRACE_BO_SIZE); + + ac_vm_fault_occured(device->physical_device->rad_info.chip_class, + &device->dmesg_timestamp, NULL); + + return true; +} + +static void +radv_dump_trace(struct radv_device *device, struct radeon_winsys_cs *cs) +{ + const char *filename = getenv("RADV_TRACE_FILE"); + FILE *f = fopen(filename, "w"); + + if (!f) { + fprintf(stderr, "Failed to write trace dump to %s\n", filename); + return; + } + + fprintf(f, "Trace ID: %x\n", *device->trace_id_ptr); + device->ws->cs_dump(cs, f, (const int*)device->trace_id_ptr, 2); + fclose(f); +} + +static void +radv_dump_mmapped_reg(struct radv_device *device, FILE *f, unsigned offset) +{ + struct radeon_winsys *ws = device->ws; + uint32_t value; + + if (ws->read_registers(ws, offset, 1, &value)) + ac_dump_reg(f, device->physical_device->rad_info.chip_class, + offset, value, ~0); +} + +static void +radv_dump_debug_registers(struct radv_device *device, FILE *f) +{ + struct radeon_info *info = &device->physical_device->rad_info; + + if (info->drm_major == 2 && info->drm_minor < 42) + return; /* no radeon support */ + + fprintf(f, "Memory-mapped registers:\n"); + radv_dump_mmapped_reg(device, f, R_008010_GRBM_STATUS); + + /* No other registers can be read on DRM < 3.1.0. */ + if (info->drm_major < 3 || info->drm_minor < 1) { + fprintf(f, "\n"); + return; + } + + radv_dump_mmapped_reg(device, f, R_008008_GRBM_STATUS2); + radv_dump_mmapped_reg(device, f, R_008014_GRBM_STATUS_SE0); + radv_dump_mmapped_reg(device, f, R_008018_GRBM_STATUS_SE1); + radv_dump_mmapped_reg(device, f, R_008038_GRBM_STATUS_SE2); + radv_dump_mmapped_reg(device, f, R_00803C_GRBM_STATUS_SE3); + radv_dump_mmapped_reg(device, f, R_00D034_SDMA0_STATUS_REG); + radv_dump_mmapped_reg(device, f, R_00D834_SDMA1_STATUS_REG); + if (info->chip_class <= VI) { + radv_dump_mmapped_reg(device, f, R_000E50_SRBM_STATUS); + radv_dump_mmapped_reg(device, f, R_000E4C_SRBM_STATUS2); + radv_dump_mmapped_reg(device, f, R_000E54_SRBM_STATUS3); + } + radv_dump_mmapped_reg(device, f, R_008680_CP_STAT); + radv_dump_mmapped_reg(device, f, R_008674_CP_STALLED_STAT1); + radv_dump_mmapped_reg(device, f, R_008678_CP_STALLED_STAT2); + radv_dump_mmapped_reg(device, f, R_008670_CP_STALLED_STAT3); + radv_dump_mmapped_reg(device, f, R_008210_CP_CPC_STATUS); + radv_dump_mmapped_reg(device, f, R_008214_CP_CPC_BUSY_STAT); + radv_dump_mmapped_reg(device, f, R_008218_CP_CPC_STALLED_STAT1); + radv_dump_mmapped_reg(device, f, R_00821C_CP_CPF_STATUS); + radv_dump_mmapped_reg(device, f, R_008220_CP_CPF_BUSY_STAT); + radv_dump_mmapped_reg(device, f, R_008224_CP_CPF_STALLED_STAT1); + fprintf(f, "\n"); +} + +static const char * +radv_get_descriptor_name(enum VkDescriptorType type) +{ + switch (type) { + case VK_DESCRIPTOR_TYPE_SAMPLER: + return "SAMPLER"; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + return "COMBINED_IMAGE_SAMPLER"; + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + return "SAMPLED_IMAGE"; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + return "STORAGE_IMAGE"; + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + return "UNIFORM_TEXEL_BUFFER"; + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + return "STORAGE_TEXEL_BUFFER"; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + return "UNIFORM_BUFFER"; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + return "STORAGE_BUFFER"; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + return "UNIFORM_BUFFER_DYNAMIC"; + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + return "STORAGE_BUFFER_DYNAMIC"; + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + return "INPUT_ATTACHMENT"; + default: + return "UNKNOWN"; + } +} + +static void +radv_dump_buffer_descriptor(enum chip_class chip_class, const uint32_t *desc, + FILE *f) +{ + fprintf(f, COLOR_CYAN " Buffer:" COLOR_RESET "\n"); + for (unsigned j = 0; j < 4; j++) + ac_dump_reg(f, chip_class, R_008F00_SQ_BUF_RSRC_WORD0 + j * 4, + desc[j], 0xffffffff); +} + +static void +radv_dump_image_descriptor(enum chip_class chip_class, const uint32_t *desc, + FILE *f) +{ + fprintf(f, COLOR_CYAN " Image:" COLOR_RESET "\n"); + for (unsigned j = 0; j < 8; j++) + ac_dump_reg(f, chip_class, R_008F10_SQ_IMG_RSRC_WORD0 + j * 4, + desc[j], 0xffffffff); + + fprintf(f, COLOR_CYAN " FMASK:" COLOR_RESET "\n"); + for (unsigned j = 0; j < 8; j++) + ac_dump_reg(f, chip_class, R_008F10_SQ_IMG_RSRC_WORD0 + j * 4, + desc[8 + j], 0xffffffff); +} + +static void +radv_dump_sampler_descriptor(enum chip_class chip_class, const uint32_t *desc, + FILE *f) +{ + fprintf(f, COLOR_CYAN " Sampler state:" COLOR_RESET "\n"); + for (unsigned j = 0; j < 4; j++) { + ac_dump_reg(f, chip_class, R_008F30_SQ_IMG_SAMP_WORD0 + j * 4, + desc[j], 0xffffffff); + } +} + +static void +radv_dump_combined_image_sampler_descriptor(enum chip_class chip_class, + const uint32_t *desc, FILE *f) +{ + radv_dump_image_descriptor(chip_class, desc, f); + radv_dump_sampler_descriptor(chip_class, desc + 16, f); +} + +static void +radv_dump_descriptor_set(enum chip_class chip_class, + struct radv_descriptor_set *set, unsigned id, FILE *f) +{ + const struct radv_descriptor_set_layout *layout; + int i; + + if (!set) + return; + layout = set->layout; + + fprintf(f, "** descriptor set (%d) **\n", id); + fprintf(f, "va: 0x%"PRIx64"\n", set->va); + fprintf(f, "size: %d\n", set->size); + fprintf(f, "mapped_ptr:\n"); + + for (i = 0; i < set->size / 4; i++) { + fprintf(f, "\t[0x%x] = 0x%08x\n", i, set->mapped_ptr[i]); + } + fprintf(f, "\n"); + + fprintf(f, "\t*** layout ***\n"); + fprintf(f, "\tbinding_count: %d\n", layout->binding_count); + fprintf(f, "\tsize: %d\n", layout->size); + fprintf(f, "\tshader_stages: %x\n", layout->shader_stages); + fprintf(f, "\tdynamic_shader_stages: %x\n", + layout->dynamic_shader_stages); + fprintf(f, "\tbuffer_count: %d\n", layout->buffer_count); + fprintf(f, "\tdynamic_offset_count: %d\n", + layout->dynamic_offset_count); + fprintf(f, "\n"); + + for (i = 0; i < set->layout->binding_count; i++) { + uint32_t *desc = + set->mapped_ptr + layout->binding[i].offset / 4; + + fprintf(f, "\t\t**** binding layout (%d) ****\n", i); + fprintf(f, "\t\ttype: %s\n", + radv_get_descriptor_name(layout->binding[i].type)); + fprintf(f, "\t\tarray_size: %d\n", + layout->binding[i].array_size); + fprintf(f, "\t\toffset: %d\n", + layout->binding[i].offset); + fprintf(f, "\t\tbuffer_offset: %d\n", + layout->binding[i].buffer_offset); + fprintf(f, "\t\tdynamic_offset_offset: %d\n", + layout->binding[i].dynamic_offset_offset); + fprintf(f, "\t\tdynamic_offset_count: %d\n", + layout->binding[i].dynamic_offset_count); + fprintf(f, "\t\tsize: %d\n", + layout->binding[i].size); + fprintf(f, "\t\timmutable_samplers_offset: %d\n", + layout->binding[i].immutable_samplers_offset); + fprintf(f, "\t\timmutable_samplers_equal: %d\n", + layout->binding[i].immutable_samplers_equal); + fprintf(f, "\n"); + + switch (layout->binding[i].type) { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + radv_dump_buffer_descriptor(chip_class, desc, f); + break; + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + radv_dump_image_descriptor(chip_class, desc, f); + break; + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + radv_dump_combined_image_sampler_descriptor(chip_class, desc, f); + break; + case VK_DESCRIPTOR_TYPE_SAMPLER: + radv_dump_sampler_descriptor(chip_class, desc, f); + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + /* todo */ + break; + default: + assert(!"unknown descriptor type"); + break; + } + fprintf(f, "\n"); + } + fprintf(f, "\n\n"); +} + +static void +radv_dump_descriptors(struct radv_pipeline *pipeline, FILE *f) +{ + struct radv_device *device = pipeline->device; + enum chip_class chip_class = device->physical_device->rad_info.chip_class; + uint64_t *ptr = (uint64_t *)device->trace_id_ptr; + int i; + + fprintf(f, "List of descriptors:\n"); + for (i = 0; i < MAX_SETS; i++) { + struct radv_descriptor_set *set = + (struct radv_descriptor_set *)ptr[i + 3]; + + radv_dump_descriptor_set(chip_class, set, i, f); + } +} + +struct radv_shader_inst { + char text[160]; /* one disasm line */ + unsigned offset; /* instruction offset */ + unsigned size; /* instruction size = 4 or 8 */ +}; + +/* Split a disassembly string into lines and add them to the array pointed + * to by "instructions". */ +static void si_add_split_disasm(const char *disasm, + uint64_t start_addr, + unsigned *num, + struct radv_shader_inst *instructions) +{ + struct radv_shader_inst *last_inst = *num ? &instructions[*num - 1] : NULL; + char *next; + + while ((next = strchr(disasm, '\n'))) { + struct radv_shader_inst *inst = &instructions[*num]; + unsigned len = next - disasm; + + assert(len < ARRAY_SIZE(inst->text)); + memcpy(inst->text, disasm, len); + inst->text[len] = 0; + inst->offset = last_inst ? last_inst->offset + last_inst->size : 0; + + const char *semicolon = strchr(disasm, ';'); + assert(semicolon); + /* More than 16 chars after ";" means the instruction is 8 bytes long. */ + inst->size = next - semicolon > 16 ? 8 : 4; + + snprintf(inst->text + len, ARRAY_SIZE(inst->text) - len, + " [PC=0x%"PRIx64", off=%u, size=%u]", + start_addr + inst->offset, inst->offset, inst->size); + + last_inst = inst; + (*num)++; + disasm = next + 1; + } +} + +static void +radv_dump_annotated_shader(struct radv_pipeline *pipeline, + struct radv_shader_variant *shader, + gl_shader_stage stage, + struct ac_wave_info *waves, unsigned num_waves, + FILE *f) +{ + uint64_t start_addr, end_addr; + unsigned i; + + if (!shader) + return; + + start_addr = radv_buffer_get_va(shader->bo) + shader->bo_offset; + end_addr = start_addr + shader->code_size; + + /* See if any wave executes the shader. */ + for (i = 0; i < num_waves; i++) { + if (start_addr <= waves[i].pc && waves[i].pc <= end_addr) + break; + } + + if (i == num_waves) + return; /* the shader is not being executed */ + + /* Remember the first found wave. The waves are sorted according to PC. */ + waves = &waves[i]; + num_waves -= i; + + /* Get the list of instructions. + * Buffer size / 4 is the upper bound of the instruction count. + */ + unsigned num_inst = 0; + struct radv_shader_inst *instructions = + calloc(shader->code_size / 4, sizeof(struct radv_shader_inst)); + + si_add_split_disasm(shader->disasm_string, + start_addr, &num_inst, instructions); + + fprintf(f, COLOR_YELLOW "%s - annotated disassembly:" COLOR_RESET "\n", + radv_get_shader_name(shader, stage)); + + /* Print instructions with annotations. */ + for (i = 0; i < num_inst; i++) { + struct radv_shader_inst *inst = &instructions[i]; + + fprintf(f, "%s\n", inst->text); + + /* Print which waves execute the instruction right now. */ + while (num_waves && start_addr + inst->offset == waves->pc) { + fprintf(f, + " " COLOR_GREEN "^ SE%u SH%u CU%u " + "SIMD%u WAVE%u EXEC=%016"PRIx64 " ", + waves->se, waves->sh, waves->cu, waves->simd, + waves->wave, waves->exec); + + if (inst->size == 4) { + fprintf(f, "INST32=%08X" COLOR_RESET "\n", + waves->inst_dw0); + } else { + fprintf(f, "INST64=%08X %08X" COLOR_RESET "\n", + waves->inst_dw0, waves->inst_dw1); + } + + waves->matched = true; + waves = &waves[1]; + num_waves--; + } + } + + fprintf(f, "\n\n"); + free(instructions); +} + +static void +radv_dump_annotated_shaders(struct radv_pipeline *pipeline, + struct radv_shader_variant *compute_shader, + FILE *f) +{ + struct ac_wave_info waves[AC_MAX_WAVES_PER_CHIP]; + unsigned num_waves = ac_get_wave_info(waves); + unsigned mask; + + fprintf(f, COLOR_CYAN "The number of active waves = %u" COLOR_RESET + "\n\n", num_waves); + + /* Dump annotated active graphics shaders. */ + mask = pipeline->active_stages; + while (mask) { + int stage = u_bit_scan(&mask); + + radv_dump_annotated_shader(pipeline, pipeline->shaders[stage], + stage, waves, num_waves, f); + } + + radv_dump_annotated_shader(pipeline, compute_shader, + MESA_SHADER_COMPUTE, waves, num_waves, f); + + /* Print waves executing shaders that are not currently bound. */ + unsigned i; + bool found = false; + for (i = 0; i < num_waves; i++) { + if (waves[i].matched) + continue; + + if (!found) { + fprintf(f, COLOR_CYAN + "Waves not executing currently-bound shaders:" + COLOR_RESET "\n"); + found = true; + } + fprintf(f, " SE%u SH%u CU%u SIMD%u WAVE%u EXEC=%016"PRIx64 + " INST=%08X %08X PC=%"PRIx64"\n", + waves[i].se, waves[i].sh, waves[i].cu, waves[i].simd, + waves[i].wave, waves[i].exec, waves[i].inst_dw0, + waves[i].inst_dw1, waves[i].pc); + } + if (found) + fprintf(f, "\n\n"); +} + +static void +radv_dump_shader(struct radv_pipeline *pipeline, + struct radv_shader_variant *shader, gl_shader_stage stage, + FILE *f) +{ + if (!shader) + return; + + fprintf(f, "%s:\n\n", radv_get_shader_name(shader, stage)); + + if (shader->spirv) { + fprintf(f, "SPIRV:\n"); + radv_print_spirv(shader->spirv, shader->spirv_size, f); + } + + if (shader->nir) { + fprintf(f, "NIR:\n"); + nir_print_shader(shader->nir, f); + } + + fprintf(stderr, "DISASM:\n%s\n", shader->disasm_string); + + radv_shader_dump_stats(pipeline->device, shader, stage, f); +} + +static void +radv_dump_shaders(struct radv_pipeline *pipeline, + struct radv_shader_variant *compute_shader, FILE *f) +{ + unsigned mask; + + /* Dump active graphics shaders. */ + mask = pipeline->active_stages; + while (mask) { + int stage = u_bit_scan(&mask); + + radv_dump_shader(pipeline, pipeline->shaders[stage], stage, f); + } + + radv_dump_shader(pipeline, compute_shader, MESA_SHADER_COMPUTE, f); +} + +static void +radv_dump_graphics_state(struct radv_pipeline *graphics_pipeline, + struct radv_pipeline *compute_pipeline, FILE *f) +{ + struct radv_shader_variant *compute_shader = + compute_pipeline ? compute_pipeline->shaders[MESA_SHADER_COMPUTE] : NULL; + + if (!graphics_pipeline) + return; + + radv_dump_shaders(graphics_pipeline, compute_shader, f); + radv_dump_annotated_shaders(graphics_pipeline, compute_shader, f); + radv_dump_descriptors(graphics_pipeline, f); +} + +static void +radv_dump_compute_state(struct radv_pipeline *compute_pipeline, FILE *f) +{ + if (!compute_pipeline) + return; + + radv_dump_shaders(compute_pipeline, + compute_pipeline->shaders[MESA_SHADER_COMPUTE], f); + radv_dump_annotated_shaders(compute_pipeline, + compute_pipeline->shaders[MESA_SHADER_COMPUTE], + f); + radv_dump_descriptors(compute_pipeline, f); +} + +static struct radv_pipeline * +radv_get_saved_graphics_pipeline(struct radv_device *device) +{ + uint64_t *ptr = (uint64_t *)device->trace_id_ptr; + + return (struct radv_pipeline *)ptr[1]; +} + +static struct radv_pipeline * +radv_get_saved_compute_pipeline(struct radv_device *device) +{ + uint64_t *ptr = (uint64_t *)device->trace_id_ptr; + + return (struct radv_pipeline *)ptr[2]; +} + +static void +radv_dump_dmesg(FILE *f) +{ + char line[2000]; + FILE *p; + + p = popen("dmesg | tail -n60", "r"); + if (!p) + return; + + fprintf(f, "\nLast 60 lines of dmesg:\n\n"); + while (fgets(line, sizeof(line), p)) + fputs(line, f); + fprintf(f, "\n"); + + pclose(p); +} + +static void +radv_dump_enabled_options(struct radv_device *device, FILE *f) +{ + uint64_t mask; + + fprintf(f, "Enabled debug options: "); + + mask = device->instance->debug_flags; + while (mask) { + int i = u_bit_scan64(&mask); + fprintf(f, "%s, ", radv_get_debug_option_name(i)); + } + fprintf(f, "\n"); + + fprintf(f, "Enabled perftest options: "); + + mask = device->instance->perftest_flags; + while (mask) { + int i = u_bit_scan64(&mask); + fprintf(f, "%s, ", radv_get_perftest_option_name(i)); + } + fprintf(f, "\n"); +} + +static void +radv_dump_device_name(struct radv_device *device, FILE *f) +{ + struct radeon_info *info = &device->physical_device->rad_info; + char llvm_string[32] = {}, kernel_version[128] = {}; + struct utsname uname_data; + const char *chip_name; + + chip_name = device->ws->get_chip_name(device->ws); + + if (uname(&uname_data) == 0) + snprintf(kernel_version, sizeof(kernel_version), + " / %s", uname_data.release); + + if (HAVE_LLVM > 0) { + snprintf(llvm_string, sizeof(llvm_string), + ", LLVM %i.%i.%i", (HAVE_LLVM >> 8) & 0xff, + HAVE_LLVM & 0xff, MESA_LLVM_VERSION_PATCH); + } + + fprintf(f, "Device name: %s (%s DRM %i.%i.%i%s%s)\n\n", + chip_name, device->physical_device->name, + info->drm_major, info->drm_minor, info->drm_patchlevel, + kernel_version, llvm_string); +} + +static bool +radv_gpu_hang_occured(struct radv_queue *queue, enum ring_type ring) +{ + struct radeon_winsys *ws = queue->device->ws; + + if (!ws->ctx_wait_idle(queue->hw_ctx, ring, queue->queue_idx)) + return true; + + return false; +} + +void +radv_check_gpu_hangs(struct radv_queue *queue, struct radeon_winsys_cs *cs) +{ + struct radv_pipeline *graphics_pipeline, *compute_pipeline; + struct radv_device *device = queue->device; + enum ring_type ring; + uint64_t addr; + + ring = radv_queue_family_to_ring(queue->queue_family_index); + + bool hang_occurred = radv_gpu_hang_occured(queue, ring); + bool vm_fault_occurred = false; + if (queue->device->instance->debug_flags & RADV_DEBUG_VM_FAULTS) + vm_fault_occurred = ac_vm_fault_occured(device->physical_device->rad_info.chip_class, + &device->dmesg_timestamp, &addr); + if (!hang_occurred && !vm_fault_occurred) + return; + + graphics_pipeline = radv_get_saved_graphics_pipeline(device); + compute_pipeline = radv_get_saved_compute_pipeline(device); + + fprintf(stderr, "GPU hang report:\n\n"); + radv_dump_device_name(device, stderr); + + radv_dump_enabled_options(device, stderr); + radv_dump_dmesg(stderr); + + if (vm_fault_occurred) { + fprintf(stderr, "VM fault report.\n\n"); + fprintf(stderr, "Failing VM page: 0x%08"PRIx64"\n\n", addr); + } + + radv_dump_debug_registers(device, stderr); + + switch (ring) { + case RING_GFX: + radv_dump_graphics_state(graphics_pipeline, compute_pipeline, + stderr); + break; + case RING_COMPUTE: + radv_dump_compute_state(compute_pipeline, stderr); + break; + default: + assert(0); + break; + } + + radv_dump_trace(queue->device, cs); + abort(); +} + +void +radv_print_spirv(uint32_t *data, uint32_t size, FILE *fp) +{ + char path[] = "/tmp/fileXXXXXX"; + char line[2048], command[128]; + FILE *p; + int fd; + + /* Dump the binary into a temporary file. */ + fd = mkstemp(path); + if (fd < 0) + return; + + if (write(fd, data, size) == -1) + goto fail; + + sprintf(command, "spirv-dis %s", path); + + /* Disassemble using spirv-dis if installed. */ + p = popen(command, "r"); + if (p) { + while (fgets(line, sizeof(line), p)) + fprintf(fp, "%s", line); + pclose(p); + } + +fail: + close(fd); + unlink(path); +} diff --git a/lib/mesa/src/amd/vulkan/radv_extensions.c b/lib/mesa/src/amd/vulkan/radv_extensions.c new file mode 100644 index 000000000..f9268dfbe --- /dev/null +++ b/lib/mesa/src/amd/vulkan/radv_extensions.c @@ -0,0 +1,407 @@ +/* + * Copyright 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 "radv_private.h" + +#include "vk_util.h" + +/* Convert the VK_USE_PLATFORM_* defines to booleans */ +#ifdef VK_USE_PLATFORM_ANDROID_KHR +# undef VK_USE_PLATFORM_ANDROID_KHR +# define VK_USE_PLATFORM_ANDROID_KHR true +#else +# define VK_USE_PLATFORM_ANDROID_KHR false +#endif +#ifdef VK_USE_PLATFORM_WAYLAND_KHR +# undef VK_USE_PLATFORM_WAYLAND_KHR +# define VK_USE_PLATFORM_WAYLAND_KHR true +#else +# define VK_USE_PLATFORM_WAYLAND_KHR false +#endif +#ifdef VK_USE_PLATFORM_XCB_KHR +# undef VK_USE_PLATFORM_XCB_KHR +# define VK_USE_PLATFORM_XCB_KHR true +#else +# define VK_USE_PLATFORM_XCB_KHR false +#endif +#ifdef VK_USE_PLATFORM_XLIB_KHR +# undef VK_USE_PLATFORM_XLIB_KHR +# define VK_USE_PLATFORM_XLIB_KHR true +#else +# define VK_USE_PLATFORM_XLIB_KHR false +#endif + +/* And ANDROID too */ +#ifdef ANDROID +# undef ANDROID +# define ANDROID true +#else +# define ANDROID false +#endif + +#define RADV_HAS_SURFACE (VK_USE_PLATFORM_WAYLAND_KHR || VK_USE_PLATFORM_XCB_KHR || VK_USE_PLATFORM_XLIB_KHR) + +bool +radv_instance_extension_supported(const char *name) +{ + if (strcmp(name, "VK_KHR_external_memory_capabilities") == 0) + return true; + if (strcmp(name, "VK_KHR_external_semaphore_capabilities") == 0) + return true; + if (strcmp(name, "VK_KHR_get_physical_device_properties2") == 0) + return true; + if (strcmp(name, "VK_KHR_surface") == 0) + return RADV_HAS_SURFACE; + if (strcmp(name, "VK_KHR_wayland_surface") == 0) + return VK_USE_PLATFORM_WAYLAND_KHR; + if (strcmp(name, "VK_KHR_xcb_surface") == 0) + return VK_USE_PLATFORM_XCB_KHR; + if (strcmp(name, "VK_KHR_xlib_surface") == 0) + return VK_USE_PLATFORM_XLIB_KHR; + return false; +} + +VkResult radv_EnumerateInstanceExtensionProperties( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties) +{ + VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount); + + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_external_memory_capabilities", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_external_semaphore_capabilities", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_get_physical_device_properties2", + .specVersion = 1, + }; + } + } + if (RADV_HAS_SURFACE) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_surface", + .specVersion = 25, + }; + } + } + if (VK_USE_PLATFORM_WAYLAND_KHR) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_wayland_surface", + .specVersion = 6, + }; + } + } + if (VK_USE_PLATFORM_XCB_KHR) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_xcb_surface", + .specVersion = 6, + }; + } + } + if (VK_USE_PLATFORM_XLIB_KHR) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_xlib_surface", + .specVersion = 6, + }; + } + } + + return vk_outarray_status(&out); +} + +uint32_t +radv_physical_device_api_version(struct radv_physical_device *dev) +{ + return VK_MAKE_VERSION(1, 0, 57); +} + +bool +radv_physical_device_extension_supported(struct radv_physical_device *device, + const char *name) +{ + if (strcmp(name, "VK_KHR_bind_memory2") == 0) + return true; + if (strcmp(name, "VK_KHR_dedicated_allocation") == 0) + return true; + if (strcmp(name, "VK_KHR_descriptor_update_template") == 0) + return true; + if (strcmp(name, "VK_KHR_external_memory") == 0) + return true; + if (strcmp(name, "VK_KHR_external_memory_fd") == 0) + return true; + if (strcmp(name, "VK_KHR_external_semaphore") == 0) + return device->rad_info.has_syncobj; + if (strcmp(name, "VK_KHR_external_semaphore_fd") == 0) + return device->rad_info.has_syncobj; + if (strcmp(name, "VK_KHR_get_memory_requirements2") == 0) + return true; + if (strcmp(name, "VK_KHR_image_format_list") == 0) + return true; + if (strcmp(name, "VK_KHR_incremental_present") == 0) + return true; + if (strcmp(name, "VK_KHR_maintenance1") == 0) + return true; + if (strcmp(name, "VK_KHR_maintenance2") == 0) + return true; + if (strcmp(name, "VK_KHR_push_descriptor") == 0) + return true; + if (strcmp(name, "VK_KHR_relaxed_block_layout") == 0) + return true; + if (strcmp(name, "VK_KHR_sampler_mirror_clamp_to_edge") == 0) + return true; + if (strcmp(name, "VK_KHR_shader_draw_parameters") == 0) + return true; + if (strcmp(name, "VK_KHR_storage_buffer_storage_class") == 0) + return true; + if (strcmp(name, "VK_KHR_swapchain") == 0) + return RADV_HAS_SURFACE; + if (strcmp(name, "VK_KHR_variable_pointers") == 0) + return true; + if (strcmp(name, "VK_KHX_multiview") == 0) + return false; + if (strcmp(name, "VK_EXT_global_priority") == 0) + return device->rad_info.has_ctx_priority; + if (strcmp(name, "VK_AMD_draw_indirect_count") == 0) + return true; + if (strcmp(name, "VK_AMD_rasterization_order") == 0) + return device->rad_info.chip_class >= VI && device->rad_info.max_se >= 2; + return false; +} + +VkResult radv_EnumerateDeviceExtensionProperties( + VkPhysicalDevice physicalDevice, + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties) +{ + RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); + VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount); + (void)device; + + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_bind_memory2", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_dedicated_allocation", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_descriptor_update_template", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_external_memory", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_external_memory_fd", + .specVersion = 1, + }; + } + } + if (device->rad_info.has_syncobj) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_external_semaphore", + .specVersion = 1, + }; + } + } + if (device->rad_info.has_syncobj) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_external_semaphore_fd", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_get_memory_requirements2", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_image_format_list", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_incremental_present", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_maintenance1", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_maintenance2", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_push_descriptor", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_relaxed_block_layout", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_sampler_mirror_clamp_to_edge", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_shader_draw_parameters", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_storage_buffer_storage_class", + .specVersion = 1, + }; + } + } + if (RADV_HAS_SURFACE) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_swapchain", + .specVersion = 68, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHR_variable_pointers", + .specVersion = 1, + }; + } + } + if (false) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_KHX_multiview", + .specVersion = 1, + }; + } + } + if (device->rad_info.has_ctx_priority) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_EXT_global_priority", + .specVersion = 1, + }; + } + } + if (true) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_AMD_draw_indirect_count", + .specVersion = 1, + }; + } + } + if (device->rad_info.chip_class >= VI && device->rad_info.max_se >= 2) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "VK_AMD_rasterization_order", + .specVersion = 1, + }; + } + } + + return vk_outarray_status(&out); +} diff --git a/lib/mesa/src/amd/vulkan/radv_extensions.py b/lib/mesa/src/amd/vulkan/radv_extensions.py new file mode 100644 index 000000000..43c0fa740 --- /dev/null +++ b/lib/mesa/src/amd/vulkan/radv_extensions.py @@ -0,0 +1,278 @@ +COPYRIGHT = """\ +/* + * Copyright 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 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 argparse +import copy +import re +import xml.etree.cElementTree as et + +from mako.template import Template + +MAX_API_VERSION = '1.0.57' + +class Extension: + def __init__(self, name, ext_version, enable): + self.name = name + self.ext_version = int(ext_version) + if enable is True: + self.enable = 'true'; + elif enable is False: + self.enable = 'false'; + else: + self.enable = enable; + +# On Android, we disable all surface and swapchain extensions. Android's Vulkan +# loader implements VK_KHR_surface and VK_KHR_swapchain, and applications +# cannot access the driver's implementation. Moreoever, if the driver exposes +# the those extension strings, then tests dEQP-VK.api.info.instance.extensions +# and dEQP-VK.api.info.device fail due to the duplicated strings. +EXTENSIONS = [ + Extension('VK_KHR_bind_memory2', 1, True), + Extension('VK_KHR_dedicated_allocation', 1, True), + Extension('VK_KHR_descriptor_update_template', 1, True), + Extension('VK_KHR_external_memory', 1, True), + Extension('VK_KHR_external_memory_capabilities', 1, True), + Extension('VK_KHR_external_memory_fd', 1, True), + Extension('VK_KHR_external_semaphore', 1, 'device->rad_info.has_syncobj'), + Extension('VK_KHR_external_semaphore_capabilities', 1, True), + Extension('VK_KHR_external_semaphore_fd', 1, 'device->rad_info.has_syncobj'), + Extension('VK_KHR_get_memory_requirements2', 1, True), + Extension('VK_KHR_get_physical_device_properties2', 1, True), + Extension('VK_KHR_image_format_list', 1, True), + Extension('VK_KHR_incremental_present', 1, True), + Extension('VK_KHR_maintenance1', 1, True), + Extension('VK_KHR_maintenance2', 1, True), + Extension('VK_KHR_push_descriptor', 1, True), + Extension('VK_KHR_relaxed_block_layout', 1, True), + Extension('VK_KHR_sampler_mirror_clamp_to_edge', 1, True), + Extension('VK_KHR_shader_draw_parameters', 1, True), + Extension('VK_KHR_storage_buffer_storage_class', 1, True), + Extension('VK_KHR_surface', 25, 'RADV_HAS_SURFACE'), + Extension('VK_KHR_swapchain', 68, 'RADV_HAS_SURFACE'), + Extension('VK_KHR_variable_pointers', 1, True), + Extension('VK_KHR_wayland_surface', 6, 'VK_USE_PLATFORM_WAYLAND_KHR'), + Extension('VK_KHR_xcb_surface', 6, 'VK_USE_PLATFORM_XCB_KHR'), + Extension('VK_KHR_xlib_surface', 6, 'VK_USE_PLATFORM_XLIB_KHR'), + Extension('VK_KHX_multiview', 1, False), + Extension('VK_EXT_global_priority', 1, 'device->rad_info.has_ctx_priority'), + Extension('VK_AMD_draw_indirect_count', 1, True), + Extension('VK_AMD_rasterization_order', 1, 'device->rad_info.chip_class >= VI && device->rad_info.max_se >= 2'), +] + +class VkVersion: + def __init__(self, string): + split = string.split('.') + self.major = int(split[0]) + self.minor = int(split[1]) + if len(split) > 2: + assert len(split) == 3 + self.patch = int(split[2]) + else: + self.patch = None + + # Sanity check. The range bits are required by the definition of the + # VK_MAKE_VERSION macro + assert self.major < 1024 and self.minor < 1024 + assert self.patch is None or self.patch < 4096 + assert(str(self) == string) + + def __str__(self): + ver_list = [str(self.major), str(self.minor)] + if self.patch is not None: + ver_list.append(str(self.patch)) + return '.'.join(ver_list) + + def c_vk_version(self): + ver_list = [str(self.major), str(self.minor), str(self.patch)] + return 'VK_MAKE_VERSION(' + ', '.join(ver_list) + ')' + + def __int_ver(self): + # This is just an expansion of VK_VERSION + patch = self.patch if self.patch is not None else 0 + return (self.major << 22) | (self.minor << 12) | patch + + def __cmp__(self, other): + # If only one of them has a patch version, "ignore" it by making + # other's patch version match self. + if (self.patch is None) != (other.patch is None): + other = copy.copy(other) + other.patch = self.patch + + return self.__int_ver().__cmp__(other.__int_ver()) + +MAX_API_VERSION = VkVersion(MAX_API_VERSION) + +def _init_exts_from_xml(xml): + """ Walk the Vulkan XML and fill out extra extension information. """ + + xml = et.parse(xml) + + ext_name_map = {} + for ext in EXTENSIONS: + ext_name_map[ext.name] = ext + + for ext_elem in xml.findall('.extensions/extension'): + ext_name = ext_elem.attrib['name'] + if ext_name not in ext_name_map: + continue + + # Workaround for VK_ANDROID_native_buffer. Its <extension> element in + # vk.xml lists it as supported="disabled" and provides only a stub + # definition. Its <extension> element in Mesa's custom + # vk_android_native_buffer.xml, though, lists it as + # supported='android-vendor' and fully defines the extension. We want + # to skip the <extension> element in vk.xml. + if ext_elem.attrib['supported'] == 'disabled': + assert ext_name == 'VK_ANDROID_native_buffer' + continue + + ext = ext_name_map[ext_name] + ext.type = ext_elem.attrib['type'] + +_TEMPLATE = Template(COPYRIGHT + """ +#include "radv_private.h" + +#include "vk_util.h" + +/* Convert the VK_USE_PLATFORM_* defines to booleans */ +%for platform in ['ANDROID', 'WAYLAND', 'XCB', 'XLIB']: +#ifdef VK_USE_PLATFORM_${platform}_KHR +# undef VK_USE_PLATFORM_${platform}_KHR +# define VK_USE_PLATFORM_${platform}_KHR true +#else +# define VK_USE_PLATFORM_${platform}_KHR false +#endif +%endfor + +/* And ANDROID too */ +#ifdef ANDROID +# undef ANDROID +# define ANDROID true +#else +# define ANDROID false +#endif + +#define RADV_HAS_SURFACE (VK_USE_PLATFORM_WAYLAND_KHR || \\ + VK_USE_PLATFORM_XCB_KHR || \\ + VK_USE_PLATFORM_XLIB_KHR) + +bool +radv_instance_extension_supported(const char *name) +{ +%for ext in instance_extensions: + if (strcmp(name, "${ext.name}") == 0) + return ${ext.enable}; +%endfor + return false; +} + +VkResult radv_EnumerateInstanceExtensionProperties( + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties) +{ + VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount); + +%for ext in instance_extensions: + if (${ext.enable}) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "${ext.name}", + .specVersion = ${ext.ext_version}, + }; + } + } +%endfor + + return vk_outarray_status(&out); +} + +uint32_t +radv_physical_device_api_version(struct radv_physical_device *dev) +{ + return ${MAX_API_VERSION.c_vk_version()}; +} + +bool +radv_physical_device_extension_supported(struct radv_physical_device *device, + const char *name) +{ +%for ext in device_extensions: + if (strcmp(name, "${ext.name}") == 0) + return ${ext.enable}; +%endfor + return false; +} + +VkResult radv_EnumerateDeviceExtensionProperties( + VkPhysicalDevice physicalDevice, + const char* pLayerName, + uint32_t* pPropertyCount, + VkExtensionProperties* pProperties) +{ + RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice); + VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount); + (void)device; + +%for ext in device_extensions: + if (${ext.enable}) { + vk_outarray_append(&out, prop) { + *prop = (VkExtensionProperties) { + .extensionName = "${ext.name}", + .specVersion = ${ext.ext_version}, + }; + } + } +%endfor + + return vk_outarray_status(&out); +} +""") + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--out', help='Output C file.', required=True) + parser.add_argument('--xml', + help='Vulkan API XML file.', + required=True, + action='append', + dest='xml_files') + args = parser.parse_args() + + for filename in args.xml_files: + _init_exts_from_xml(filename) + + for ext in EXTENSIONS: + assert ext.type == 'instance' or ext.type == 'device' + + template_env = { + 'MAX_API_VERSION': MAX_API_VERSION, + 'instance_extensions': [e for e in EXTENSIONS if e.type == 'instance'], + 'device_extensions': [e for e in EXTENSIONS if e.type == 'device'], + } + + with open(args.out, 'w') as f: + f.write(_TEMPLATE.render(**template_env)) diff --git a/lib/mesa/src/amd/vulkan/radv_pass.c b/lib/mesa/src/amd/vulkan/radv_pass.c index 17eff3937..a52dae39d 100644 --- a/lib/mesa/src/amd/vulkan/radv_pass.c +++ b/lib/mesa/src/amd/vulkan/radv_pass.c @@ -26,6 +26,8 @@ */ #include "radv_private.h" +#include "vk_util.h" + VkResult radv_CreateRenderPass( VkDevice _device, const VkRenderPassCreateInfo* pCreateInfo, @@ -36,6 +38,7 @@ VkResult radv_CreateRenderPass( struct radv_render_pass *pass; size_t size; size_t attachments_offset; + VkRenderPassMultiviewCreateInfoKHX *multiview_info = NULL; assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO); @@ -54,6 +57,16 @@ VkResult radv_CreateRenderPass( pass->subpass_count = pCreateInfo->subpassCount; pass->attachments = (void *) pass + attachments_offset; + vk_foreach_struct(ext, pCreateInfo->pNext) { + switch(ext->sType) { + case VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO_KHX: + multiview_info = ( VkRenderPassMultiviewCreateInfoKHX*)ext; + break; + default: + break; + } + } + for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { struct radv_render_pass_attachment *att = &pass->attachments[i]; @@ -97,6 +110,8 @@ VkResult radv_CreateRenderPass( subpass->input_count = desc->inputAttachmentCount; subpass->color_count = desc->colorAttachmentCount; + if (multiview_info) + subpass->view_mask = multiview_info->pViewMasks[i]; if (desc->inputAttachmentCount > 0) { subpass->input_attachments = p; @@ -105,6 +120,8 @@ VkResult radv_CreateRenderPass( for (uint32_t j = 0; j < desc->inputAttachmentCount; j++) { subpass->input_attachments[j] = desc->pInputAttachments[j]; + if (desc->pInputAttachments[j].attachment != VK_ATTACHMENT_UNUSED) + pass->attachments[desc->pInputAttachments[j].attachment].view_mask |= subpass->view_mask; } } @@ -115,6 +132,8 @@ VkResult radv_CreateRenderPass( for (uint32_t j = 0; j < desc->colorAttachmentCount; j++) { subpass->color_attachments[j] = desc->pColorAttachments[j]; + if (desc->pColorAttachments[j].attachment != VK_ATTACHMENT_UNUSED) + pass->attachments[desc->pColorAttachments[j].attachment].view_mask |= subpass->view_mask; } } @@ -127,14 +146,18 @@ VkResult radv_CreateRenderPass( uint32_t a = desc->pResolveAttachments[j].attachment; subpass->resolve_attachments[j] = desc->pResolveAttachments[j]; - if (a != VK_ATTACHMENT_UNUSED) + if (a != VK_ATTACHMENT_UNUSED) { subpass->has_resolve = true; + pass->attachments[desc->pResolveAttachments[j].attachment].view_mask |= subpass->view_mask; + } } } if (desc->pDepthStencilAttachment) { subpass->depth_stencil_attachment = *desc->pDepthStencilAttachment; + if (desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) + pass->attachments[desc->pDepthStencilAttachment->attachment].view_mask |= subpass->view_mask; } else { subpass->depth_stencil_attachment.attachment = VK_ATTACHMENT_UNUSED; } diff --git a/lib/mesa/src/amd/vulkan/radv_shader.c b/lib/mesa/src/amd/vulkan/radv_shader.c new file mode 100644 index 000000000..83e2e675e --- /dev/null +++ b/lib/mesa/src/amd/vulkan/radv_shader.c @@ -0,0 +1,671 @@ +/* + * Copyright © 2016 Red Hat. + * Copyright © 2016 Bas Nieuwenhuizen + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "util/mesa-sha1.h" +#include "util/u_atomic.h" +#include "radv_debug.h" +#include "radv_private.h" +#include "radv_shader.h" +#include "nir/nir.h" +#include "nir/nir_builder.h" +#include "spirv/nir_spirv.h" + +#include <llvm-c/Core.h> +#include <llvm-c/TargetMachine.h> + +#include "sid.h" +#include "gfx9d.h" +#include "ac_binary.h" +#include "ac_llvm_util.h" +#include "ac_nir_to_llvm.h" +#include "vk_format.h" +#include "util/debug.h" +#include "ac_exp_param.h" + +static const struct nir_shader_compiler_options nir_options = { + .vertex_id_zero_based = true, + .lower_scmp = true, + .lower_flrp32 = true, + .lower_fsat = true, + .lower_fdiv = true, + .lower_sub = true, + .lower_pack_snorm_2x16 = true, + .lower_pack_snorm_4x8 = true, + .lower_pack_unorm_2x16 = true, + .lower_pack_unorm_4x8 = true, + .lower_unpack_snorm_2x16 = true, + .lower_unpack_snorm_4x8 = true, + .lower_unpack_unorm_2x16 = true, + .lower_unpack_unorm_4x8 = true, + .lower_extract_byte = true, + .lower_extract_word = true, + .lower_ffma = true, + .max_unroll_iterations = 32 +}; + +VkResult radv_CreateShaderModule( + VkDevice _device, + const VkShaderModuleCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkShaderModule* pShaderModule) +{ + RADV_FROM_HANDLE(radv_device, device, _device); + struct radv_shader_module *module; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO); + assert(pCreateInfo->flags == 0); + + module = vk_alloc2(&device->alloc, pAllocator, + sizeof(*module) + pCreateInfo->codeSize, 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + if (module == NULL) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + module->nir = NULL; + module->size = pCreateInfo->codeSize; + memcpy(module->data, pCreateInfo->pCode, module->size); + + _mesa_sha1_compute(module->data, module->size, module->sha1); + + *pShaderModule = radv_shader_module_to_handle(module); + + return VK_SUCCESS; +} + +void radv_DestroyShaderModule( + VkDevice _device, + VkShaderModule _module, + const VkAllocationCallbacks* pAllocator) +{ + RADV_FROM_HANDLE(radv_device, device, _device); + RADV_FROM_HANDLE(radv_shader_module, module, _module); + + if (!module) + return; + + vk_free2(&device->alloc, pAllocator, module); +} + +bool +radv_lower_indirect_derefs(struct nir_shader *nir, + struct radv_physical_device *device) +{ + /* While it would be nice not to have this flag, we are constrained + * by the reality that LLVM 5.0 doesn't have working VGPR indexing + * on GFX9. + */ + bool llvm_has_working_vgpr_indexing = + device->rad_info.chip_class <= VI; + + /* TODO: Indirect indexing of GS inputs is unimplemented. + * + * TCS and TES load inputs directly from LDS or offchip memory, so + * indirect indexing is trivial. + */ + nir_variable_mode indirect_mask = 0; + if (nir->info.stage == MESA_SHADER_GEOMETRY || + (nir->info.stage != MESA_SHADER_TESS_CTRL && + nir->info.stage != MESA_SHADER_TESS_EVAL && + !llvm_has_working_vgpr_indexing)) { + indirect_mask |= nir_var_shader_in; + } + if (!llvm_has_working_vgpr_indexing && + nir->info.stage != MESA_SHADER_TESS_CTRL) + indirect_mask |= nir_var_shader_out; + + /* TODO: We shouldn't need to do this, however LLVM isn't currently + * smart enough to handle indirects without causing excess spilling + * causing the gpu to hang. + * + * See the following thread for more details of the problem: + * https://lists.freedesktop.org/archives/mesa-dev/2017-July/162106.html + */ + indirect_mask |= nir_var_local; + + return nir_lower_indirect_derefs(nir, indirect_mask); +} + +void +radv_optimize_nir(struct nir_shader *shader) +{ + bool progress; + + do { + progress = false; + + NIR_PASS_V(shader, nir_lower_vars_to_ssa); + NIR_PASS_V(shader, nir_lower_64bit_pack); + NIR_PASS_V(shader, nir_lower_alu_to_scalar); + NIR_PASS_V(shader, nir_lower_phis_to_scalar); + + NIR_PASS(progress, shader, nir_copy_prop); + NIR_PASS(progress, shader, nir_opt_remove_phis); + NIR_PASS(progress, shader, nir_opt_dce); + if (nir_opt_trivial_continues(shader)) { + progress = true; + NIR_PASS(progress, shader, nir_copy_prop); + NIR_PASS(progress, shader, nir_opt_remove_phis); + NIR_PASS(progress, shader, nir_opt_dce); + } + NIR_PASS(progress, shader, nir_opt_if); + NIR_PASS(progress, shader, nir_opt_dead_cf); + NIR_PASS(progress, shader, nir_opt_cse); + NIR_PASS(progress, shader, nir_opt_peephole_select, 8); + NIR_PASS(progress, shader, nir_opt_algebraic); + NIR_PASS(progress, shader, nir_opt_constant_folding); + NIR_PASS(progress, shader, nir_opt_undef); + NIR_PASS(progress, shader, nir_opt_conditional_discard); + if (shader->options->max_unroll_iterations) { + NIR_PASS(progress, shader, nir_opt_loop_unroll, 0); + } + } while (progress); +} + +nir_shader * +radv_shader_compile_to_nir(struct radv_device *device, + struct radv_shader_module *module, + const char *entrypoint_name, + gl_shader_stage stage, + const VkSpecializationInfo *spec_info) +{ + if (strcmp(entrypoint_name, "main") != 0) { + radv_finishme("Multiple shaders per module not really supported"); + } + + nir_shader *nir; + nir_function *entry_point; + if (module->nir) { + /* Some things such as our meta clear/blit code will give us a NIR + * shader directly. In that case, we just ignore the SPIR-V entirely + * and just use the NIR shader */ + nir = module->nir; + nir->options = &nir_options; + nir_validate_shader(nir); + + assert(exec_list_length(&nir->functions) == 1); + struct exec_node *node = exec_list_get_head(&nir->functions); + entry_point = exec_node_data(nir_function, node, node); + } else { + uint32_t *spirv = (uint32_t *) module->data; + assert(module->size % 4 == 0); + + if (device->instance->debug_flags & RADV_DEBUG_DUMP_SPIRV) + radv_print_spirv(spirv, module->size, stderr); + + uint32_t num_spec_entries = 0; + struct nir_spirv_specialization *spec_entries = NULL; + if (spec_info && spec_info->mapEntryCount > 0) { + num_spec_entries = spec_info->mapEntryCount; + spec_entries = malloc(num_spec_entries * sizeof(*spec_entries)); + for (uint32_t i = 0; i < num_spec_entries; i++) { + VkSpecializationMapEntry entry = spec_info->pMapEntries[i]; + const void *data = spec_info->pData + entry.offset; + assert(data + entry.size <= spec_info->pData + spec_info->dataSize); + + spec_entries[i].id = spec_info->pMapEntries[i].constantID; + if (spec_info->dataSize == 8) + spec_entries[i].data64 = *(const uint64_t *)data; + else + spec_entries[i].data32 = *(const uint32_t *)data; + } + } + const struct nir_spirv_supported_extensions supported_ext = { + .draw_parameters = true, + .float64 = true, + .image_read_without_format = true, + .image_write_without_format = true, + .tessellation = true, + .int64 = true, + .multiview = true, + .variable_pointers = true, + }; + entry_point = spirv_to_nir(spirv, module->size / 4, + spec_entries, num_spec_entries, + stage, entrypoint_name, &supported_ext, &nir_options); + nir = entry_point->shader; + assert(nir->info.stage == stage); + nir_validate_shader(nir); + + free(spec_entries); + + /* We have to lower away local constant initializers right before we + * inline functions. That way they get properly initialized at the top + * of the function and not at the top of its caller. + */ + NIR_PASS_V(nir, nir_lower_constant_initializers, nir_var_local); + NIR_PASS_V(nir, nir_lower_returns); + NIR_PASS_V(nir, nir_inline_functions); + + /* Pick off the single entrypoint that we want */ + foreach_list_typed_safe(nir_function, func, node, &nir->functions) { + if (func != entry_point) + exec_node_remove(&func->node); + } + assert(exec_list_length(&nir->functions) == 1); + entry_point->name = ralloc_strdup(entry_point, "main"); + + NIR_PASS_V(nir, nir_remove_dead_variables, + nir_var_shader_in | nir_var_shader_out | nir_var_system_value); + + /* Now that we've deleted all but the main function, we can go ahead and + * lower the rest of the constant initializers. + */ + NIR_PASS_V(nir, nir_lower_constant_initializers, ~0); + NIR_PASS_V(nir, nir_lower_system_values); + NIR_PASS_V(nir, nir_lower_clip_cull_distance_arrays); + } + + /* Vulkan uses the separate-shader linking model */ + nir->info.separate_shader = true; + + nir_shader_gather_info(nir, entry_point->impl); + + static const nir_lower_tex_options tex_options = { + .lower_txp = ~0, + }; + + nir_lower_tex(nir, &tex_options); + + nir_lower_vars_to_ssa(nir); + nir_lower_var_copies(nir); + nir_lower_global_vars_to_local(nir); + nir_remove_dead_variables(nir, nir_var_local); + radv_lower_indirect_derefs(nir, device->physical_device); + radv_optimize_nir(nir); + + return nir; +} + +void * +radv_alloc_shader_memory(struct radv_device *device, + struct radv_shader_variant *shader) +{ + mtx_lock(&device->shader_slab_mutex); + list_for_each_entry(struct radv_shader_slab, slab, &device->shader_slabs, slabs) { + uint64_t offset = 0; + list_for_each_entry(struct radv_shader_variant, s, &slab->shaders, slab_list) { + if (s->bo_offset - offset >= shader->code_size) { + shader->bo = slab->bo; + shader->bo_offset = offset; + list_addtail(&shader->slab_list, &s->slab_list); + mtx_unlock(&device->shader_slab_mutex); + return slab->ptr + offset; + } + offset = align_u64(s->bo_offset + s->code_size, 256); + } + if (slab->size - offset >= shader->code_size) { + shader->bo = slab->bo; + shader->bo_offset = offset; + list_addtail(&shader->slab_list, &slab->shaders); + mtx_unlock(&device->shader_slab_mutex); + return slab->ptr + offset; + } + } + + mtx_unlock(&device->shader_slab_mutex); + struct radv_shader_slab *slab = calloc(1, sizeof(struct radv_shader_slab)); + + slab->size = 256 * 1024; + slab->bo = device->ws->buffer_create(device->ws, slab->size, 256, + RADEON_DOMAIN_VRAM, 0); + slab->ptr = (char*)device->ws->buffer_map(slab->bo); + list_inithead(&slab->shaders); + + mtx_lock(&device->shader_slab_mutex); + list_add(&slab->slabs, &device->shader_slabs); + + shader->bo = slab->bo; + shader->bo_offset = 0; + list_add(&shader->slab_list, &slab->shaders); + mtx_unlock(&device->shader_slab_mutex); + return slab->ptr; +} + +void +radv_destroy_shader_slabs(struct radv_device *device) +{ + list_for_each_entry_safe(struct radv_shader_slab, slab, &device->shader_slabs, slabs) { + device->ws->buffer_destroy(slab->bo); + free(slab); + } + mtx_destroy(&device->shader_slab_mutex); +} + +static void +radv_fill_shader_variant(struct radv_device *device, + struct radv_shader_variant *variant, + struct ac_shader_binary *binary, + gl_shader_stage stage) +{ + bool scratch_enabled = variant->config.scratch_bytes_per_wave > 0; + unsigned vgpr_comp_cnt = 0; + + if (scratch_enabled && !device->llvm_supports_spill) + radv_finishme("shader scratch support only available with LLVM 4.0"); + + variant->code_size = binary->code_size; + variant->rsrc2 = S_00B12C_USER_SGPR(variant->info.num_user_sgprs) | + S_00B12C_SCRATCH_EN(scratch_enabled); + + variant->rsrc1 = S_00B848_VGPRS((variant->config.num_vgprs - 1) / 4) | + S_00B848_SGPRS((variant->config.num_sgprs - 1) / 8) | + S_00B848_DX10_CLAMP(1) | + S_00B848_FLOAT_MODE(variant->config.float_mode); + + switch (stage) { + case MESA_SHADER_TESS_EVAL: + vgpr_comp_cnt = 3; + variant->rsrc2 |= S_00B12C_OC_LDS_EN(1); + break; + case MESA_SHADER_TESS_CTRL: + if (device->physical_device->rad_info.chip_class >= GFX9) + vgpr_comp_cnt = variant->info.vs.vgpr_comp_cnt; + else + variant->rsrc2 |= S_00B12C_OC_LDS_EN(1); + break; + case MESA_SHADER_VERTEX: + case MESA_SHADER_GEOMETRY: + vgpr_comp_cnt = variant->info.vs.vgpr_comp_cnt; + break; + case MESA_SHADER_FRAGMENT: + break; + case MESA_SHADER_COMPUTE: + variant->rsrc2 |= + S_00B84C_TGID_X_EN(1) | S_00B84C_TGID_Y_EN(1) | + S_00B84C_TGID_Z_EN(1) | S_00B84C_TIDIG_COMP_CNT(2) | + S_00B84C_TG_SIZE_EN(1) | + S_00B84C_LDS_SIZE(variant->config.lds_size); + break; + default: + unreachable("unsupported shader type"); + break; + } + + if (device->physical_device->rad_info.chip_class >= GFX9 && + stage == MESA_SHADER_GEOMETRY) { + /* TODO: Figure out how many we actually need. */ + variant->rsrc1 |= S_00B228_GS_VGPR_COMP_CNT(3); + variant->rsrc2 |= S_00B22C_ES_VGPR_COMP_CNT(3) | + S_00B22C_OC_LDS_EN(1); + } else if (device->physical_device->rad_info.chip_class >= GFX9 && + stage == MESA_SHADER_TESS_CTRL) + variant->rsrc1 |= S_00B428_LS_VGPR_COMP_CNT(vgpr_comp_cnt); + else + variant->rsrc1 |= S_00B128_VGPR_COMP_CNT(vgpr_comp_cnt); + + void *ptr = radv_alloc_shader_memory(device, variant); + memcpy(ptr, binary->code, binary->code_size); +} + +static struct radv_shader_variant * +shader_variant_create(struct radv_device *device, + struct radv_shader_module *module, + struct nir_shader * const *shaders, + int shader_count, + gl_shader_stage stage, + struct ac_nir_compiler_options *options, + bool gs_copy_shader, + void **code_out, + unsigned *code_size_out) +{ + enum radeon_family chip_family = device->physical_device->rad_info.family; + bool dump_shaders = device->instance->debug_flags & RADV_DEBUG_DUMP_SHADERS; + enum ac_target_machine_options tm_options = 0; + struct radv_shader_variant *variant; + struct ac_shader_binary binary; + LLVMTargetMachineRef tm; + + variant = calloc(1, sizeof(struct radv_shader_variant)); + if (!variant) + return NULL; + + options->family = chip_family; + options->chip_class = device->physical_device->rad_info.chip_class; + + if (options->supports_spill) + tm_options |= AC_TM_SUPPORTS_SPILL; + if (device->instance->perftest_flags & RADV_PERFTEST_SISCHED) + tm_options |= AC_TM_SISCHED; + tm = ac_create_target_machine(chip_family, tm_options); + + if (gs_copy_shader) { + assert(shader_count == 1); + ac_create_gs_copy_shader(tm, *shaders, &binary, &variant->config, + &variant->info, options, dump_shaders); + } else { + ac_compile_nir_shader(tm, &binary, &variant->config, + &variant->info, shaders, shader_count, options, + dump_shaders); + } + + LLVMDisposeTargetMachine(tm); + + radv_fill_shader_variant(device, variant, &binary, stage); + + if (code_out) { + *code_out = binary.code; + *code_size_out = binary.code_size; + } else + free(binary.code); + free(binary.config); + free(binary.rodata); + free(binary.global_symbol_offsets); + free(binary.relocs); + variant->ref_count = 1; + + if (device->trace_bo) { + variant->disasm_string = binary.disasm_string; + if (!gs_copy_shader && !module->nir) { + variant->nir = *shaders; + variant->spirv = (uint32_t *)module->data; + variant->spirv_size = module->size; + } + } else { + free(binary.disasm_string); + } + + return variant; +} + +struct radv_shader_variant * +radv_shader_variant_create(struct radv_device *device, + struct radv_shader_module *module, + struct nir_shader *const *shaders, + int shader_count, + struct radv_pipeline_layout *layout, + const struct ac_shader_variant_key *key, + void **code_out, + unsigned *code_size_out) +{ + struct ac_nir_compiler_options options = {0}; + + options.layout = layout; + if (key) + options.key = *key; + + options.unsafe_math = !!(device->instance->debug_flags & RADV_DEBUG_UNSAFE_MATH); + options.supports_spill = device->llvm_supports_spill; + + return shader_variant_create(device, module, shaders, shader_count, shaders[shader_count - 1]->info.stage, + &options, false, code_out, code_size_out); +} + +struct radv_shader_variant * +radv_create_gs_copy_shader(struct radv_device *device, + struct nir_shader *shader, + void **code_out, + unsigned *code_size_out, + bool multiview) +{ + struct ac_nir_compiler_options options = {0}; + + options.key.has_multiview_view_index = multiview; + + return shader_variant_create(device, NULL, &shader, 1, MESA_SHADER_VERTEX, + &options, true, code_out, code_size_out); +} + +void +radv_shader_variant_destroy(struct radv_device *device, + struct radv_shader_variant *variant) +{ + if (!p_atomic_dec_zero(&variant->ref_count)) + return; + + mtx_lock(&device->shader_slab_mutex); + list_del(&variant->slab_list); + mtx_unlock(&device->shader_slab_mutex); + + ralloc_free(variant->nir); + free(variant->disasm_string); + free(variant); +} + +uint32_t +radv_shader_stage_to_user_data_0(gl_shader_stage stage, enum chip_class chip_class, + bool has_gs, bool has_tess) +{ + switch (stage) { + case MESA_SHADER_FRAGMENT: + return R_00B030_SPI_SHADER_USER_DATA_PS_0; + case MESA_SHADER_VERTEX: + if (chip_class >= GFX9) { + return has_tess ? R_00B430_SPI_SHADER_USER_DATA_LS_0 : + has_gs ? R_00B330_SPI_SHADER_USER_DATA_ES_0 : + R_00B130_SPI_SHADER_USER_DATA_VS_0; + } + if (has_tess) + return R_00B530_SPI_SHADER_USER_DATA_LS_0; + else + return has_gs ? R_00B330_SPI_SHADER_USER_DATA_ES_0 : R_00B130_SPI_SHADER_USER_DATA_VS_0; + case MESA_SHADER_GEOMETRY: + return chip_class >= GFX9 ? R_00B330_SPI_SHADER_USER_DATA_ES_0 : + R_00B230_SPI_SHADER_USER_DATA_GS_0; + case MESA_SHADER_COMPUTE: + return R_00B900_COMPUTE_USER_DATA_0; + case MESA_SHADER_TESS_CTRL: + return chip_class >= GFX9 ? R_00B430_SPI_SHADER_USER_DATA_LS_0 : + R_00B430_SPI_SHADER_USER_DATA_HS_0; + case MESA_SHADER_TESS_EVAL: + if (chip_class >= GFX9) { + return has_gs ? R_00B330_SPI_SHADER_USER_DATA_ES_0 : + R_00B130_SPI_SHADER_USER_DATA_VS_0; + } + if (has_gs) + return R_00B330_SPI_SHADER_USER_DATA_ES_0; + else + return R_00B130_SPI_SHADER_USER_DATA_VS_0; + default: + unreachable("unknown shader"); + } +} + +const char * +radv_get_shader_name(struct radv_shader_variant *var, gl_shader_stage stage) +{ + switch (stage) { + case MESA_SHADER_VERTEX: return var->info.vs.as_ls ? "Vertex Shader as LS" : var->info.vs.as_es ? "Vertex Shader as ES" : "Vertex Shader as VS"; + case MESA_SHADER_GEOMETRY: return "Geometry Shader"; + case MESA_SHADER_FRAGMENT: return "Pixel Shader"; + case MESA_SHADER_COMPUTE: return "Compute Shader"; + case MESA_SHADER_TESS_CTRL: return "Tessellation Control Shader"; + case MESA_SHADER_TESS_EVAL: return var->info.tes.as_es ? "Tessellation Evaluation Shader as ES" : "Tessellation Evaluation Shader as VS"; + default: + return "Unknown shader"; + }; +} + +void +radv_shader_dump_stats(struct radv_device *device, + struct radv_shader_variant *variant, + gl_shader_stage stage, + FILE *file) +{ + unsigned lds_increment = device->physical_device->rad_info.chip_class >= CIK ? 512 : 256; + struct ac_shader_config *conf; + unsigned max_simd_waves; + unsigned lds_per_wave = 0; + + switch (device->physical_device->rad_info.family) { + /* These always have 8 waves: */ + case CHIP_POLARIS10: + case CHIP_POLARIS11: + case CHIP_POLARIS12: + max_simd_waves = 8; + break; + default: + max_simd_waves = 10; + } + + conf = &variant->config; + + if (stage == MESA_SHADER_FRAGMENT) { + lds_per_wave = conf->lds_size * lds_increment + + align(variant->info.fs.num_interp * 48, + lds_increment); + } + + if (conf->num_sgprs) { + if (device->physical_device->rad_info.chip_class >= VI) + max_simd_waves = MIN2(max_simd_waves, 800 / conf->num_sgprs); + else + max_simd_waves = MIN2(max_simd_waves, 512 / conf->num_sgprs); + } + + if (conf->num_vgprs) + max_simd_waves = MIN2(max_simd_waves, 256 / conf->num_vgprs); + + /* LDS is 64KB per CU (4 SIMDs), divided into 16KB blocks per SIMD + * that PS can use. + */ + if (lds_per_wave) + max_simd_waves = MIN2(max_simd_waves, 16384 / lds_per_wave); + + fprintf(file, "\n%s:\n", radv_get_shader_name(variant, stage)); + + if (stage == MESA_SHADER_FRAGMENT) { + fprintf(file, "*** SHADER CONFIG ***\n" + "SPI_PS_INPUT_ADDR = 0x%04x\n" + "SPI_PS_INPUT_ENA = 0x%04x\n", + conf->spi_ps_input_addr, conf->spi_ps_input_ena); + } + + fprintf(file, "*** SHADER STATS ***\n" + "SGPRS: %d\n" + "VGPRS: %d\n" + "Spilled SGPRs: %d\n" + "Spilled VGPRs: %d\n" + "Code Size: %d bytes\n" + "LDS: %d blocks\n" + "Scratch: %d bytes per wave\n" + "Max Waves: %d\n" + "********************\n\n\n", + conf->num_sgprs, conf->num_vgprs, + conf->spilled_sgprs, conf->spilled_vgprs, variant->code_size, + conf->lds_size, conf->scratch_bytes_per_wave, + max_simd_waves); +} diff --git a/lib/mesa/src/amd/vulkan/radv_shader.h b/lib/mesa/src/amd/vulkan/radv_shader.h new file mode 100644 index 000000000..6e4e9966c --- /dev/null +++ b/lib/mesa/src/amd/vulkan/radv_shader.h @@ -0,0 +1,123 @@ +/* + * Copyright © 2016 Red Hat. + * Copyright © 2016 Bas Nieuwenhuizen + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef RADV_SHADER_H +#define RADV_SHADER_H + +#include "radv_private.h" + +#include "nir/nir.h" + +struct radv_shader_module { + struct nir_shader *nir; + unsigned char sha1[20]; + uint32_t size; + char data[0]; +}; + +struct radv_shader_variant { + uint32_t ref_count; + + struct radeon_winsys_bo *bo; + uint64_t bo_offset; + struct ac_shader_config config; + uint32_t code_size; + struct ac_shader_variant_info info; + unsigned rsrc1; + unsigned rsrc2; + + /* debug only */ + uint32_t *spirv; + uint32_t spirv_size; + struct nir_shader *nir; + char *disasm_string; + + struct list_head slab_list; +}; + +struct radv_shader_slab { + struct list_head slabs; + struct list_head shaders; + struct radeon_winsys_bo *bo; + uint64_t size; + char *ptr; +}; + +void +radv_optimize_nir(struct nir_shader *shader); + +nir_shader * +radv_shader_compile_to_nir(struct radv_device *device, + struct radv_shader_module *module, + const char *entrypoint_name, + gl_shader_stage stage, + const VkSpecializationInfo *spec_info); + +void * +radv_alloc_shader_memory(struct radv_device *device, + struct radv_shader_variant *shader); + +void +radv_destroy_shader_slabs(struct radv_device *device); + +struct radv_shader_variant * +radv_shader_variant_create(struct radv_device *device, + struct radv_shader_module *module, + struct nir_shader *const *shaders, + int shader_count, + struct radv_pipeline_layout *layout, + const struct ac_shader_variant_key *key, + void **code_out, + unsigned *code_size_out); + +struct radv_shader_variant * +radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *nir, + void **code_out, unsigned *code_size_out, + bool multiview); + +void +radv_shader_variant_destroy(struct radv_device *device, + struct radv_shader_variant *variant); + +bool +radv_lower_indirect_derefs(struct nir_shader *nir, + struct radv_physical_device *device); + +uint32_t +radv_shader_stage_to_user_data_0(gl_shader_stage stage, enum chip_class chip_class, + bool has_gs, bool has_tess); + +const char * +radv_get_shader_name(struct radv_shader_variant *var, gl_shader_stage stage); + +void +radv_shader_dump_stats(struct radv_device *device, + struct radv_shader_variant *variant, + gl_shader_stage stage, + FILE *file); + +#endif diff --git a/lib/mesa/src/broadcom/Makefile.cle.am b/lib/mesa/src/broadcom/Makefile.cle.am new file mode 100644 index 000000000..1c262d039 --- /dev/null +++ b/lib/mesa/src/broadcom/Makefile.cle.am @@ -0,0 +1,6 @@ +noinst_LTLIBRARIES += cle/libbroadcom_cle.la + +cle_libbroadcom_cle_la_CFLAGS = \ + -I$(top_builddir)/src/broadcom/cle \ + $(AM_CFLAGS) +cle_libbroadcom_cle_la_SOURCES = $(BROADCOM_DECODER_FILES) diff --git a/lib/mesa/src/broadcom/Makefile.vc5.am b/lib/mesa/src/broadcom/Makefile.vc5.am new file mode 100644 index 000000000..3e8e28bc9 --- /dev/null +++ b/lib/mesa/src/broadcom/Makefile.vc5.am @@ -0,0 +1,20 @@ +noinst_LTLIBRARIES += libbroadcom.la + +if USE_VC5_SIMULATOR +AM_CFLAGS += $(VC5_SIMULATOR_CFLAGS) +libbroadcom_la_LDFLAGS = $(VC5_SIMULATOR_LIBS) +endif + +libbroadcom_la_SOURCES = $(BROADCOM_FILES) + +check_PROGRAMS += \ + qpu/tests/qpu_disasm \ + $(NULL) + +LDADD = \ + libbroadcom.la \ + $(top_builddir)/src/compiler/nir/libnir.la \ + $(top_builddir)/src/util/libmesautil.la \ + $(NULL) + +TESTS += $(check_PROGRAMS) diff --git a/lib/mesa/src/broadcom/cle/v3d_decoder.c b/lib/mesa/src/broadcom/cle/v3d_decoder.c new file mode 100644 index 000000000..4ac40af05 --- /dev/null +++ b/lib/mesa/src/broadcom/cle/v3d_decoder.c @@ -0,0 +1,876 @@ +/* + * Copyright © 2016 Intel Corporation + * Copyright © 2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdarg.h> +#include <string.h> +#include <expat.h> +#include <inttypes.h> +#include <zlib.h> + +#include <util/macros.h> +#include <util/ralloc.h> + +#include "v3d_decoder.h" +#include "v3d_packet_helpers.h" +#include "v3d_xml.h" + +struct v3d_spec { + uint32_t ver; + + int ncommands; + struct v3d_group *commands[256]; + int nstructs; + struct v3d_group *structs[256]; + int nregisters; + struct v3d_group *registers[256]; + int nenums; + struct v3d_enum *enums[256]; +}; + +struct location { + const char *filename; + int line_number; +}; + +struct parser_context { + XML_Parser parser; + int foo; + struct location loc; + + struct v3d_group *group; + struct v3d_enum *enoom; + + int nvalues; + struct v3d_value *values[256]; + + struct v3d_spec *spec; +}; + +const char * +v3d_group_get_name(struct v3d_group *group) +{ + return group->name; +} + +uint8_t +v3d_group_get_opcode(struct v3d_group *group) +{ + return group->opcode; +} + +struct v3d_group * +v3d_spec_find_struct(struct v3d_spec *spec, const char *name) +{ + for (int i = 0; i < spec->nstructs; i++) + if (strcmp(spec->structs[i]->name, name) == 0) + return spec->structs[i]; + + return NULL; +} + +struct v3d_group * +v3d_spec_find_register(struct v3d_spec *spec, uint32_t offset) +{ + for (int i = 0; i < spec->nregisters; i++) + if (spec->registers[i]->register_offset == offset) + return spec->registers[i]; + + return NULL; +} + +struct v3d_group * +v3d_spec_find_register_by_name(struct v3d_spec *spec, const char *name) +{ + for (int i = 0; i < spec->nregisters; i++) { + if (strcmp(spec->registers[i]->name, name) == 0) + return spec->registers[i]; + } + + return NULL; +} + +struct v3d_enum * +v3d_spec_find_enum(struct v3d_spec *spec, const char *name) +{ + for (int i = 0; i < spec->nenums; i++) + if (strcmp(spec->enums[i]->name, name) == 0) + return spec->enums[i]; + + return NULL; +} + +static void __attribute__((noreturn)) +fail(struct location *loc, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + fprintf(stderr, "%s:%d: error: ", + loc->filename, loc->line_number); + vfprintf(stderr, msg, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(EXIT_FAILURE); +} + +static void * +fail_on_null(void *p) +{ + if (p == NULL) { + fprintf(stderr, "aubinator: out of memory\n"); + exit(EXIT_FAILURE); + } + + return p; +} + +static char * +xstrdup(const char *s) +{ + return fail_on_null(strdup(s)); +} + +static void * +zalloc(size_t s) +{ + return calloc(s, 1); +} + +static void * +xzalloc(size_t s) +{ + return fail_on_null(zalloc(s)); +} + +/* We allow fields to have either a bit index, or append "b" for a byte index. + */ +static bool +is_byte_offset(const char *value) +{ + return value[strlen(value) - 1] == 'b'; +} + +static void +get_group_offset_count(const char **atts, uint32_t *offset, uint32_t *count, + uint32_t *size, bool *variable) +{ + char *p; + int i; + + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "count") == 0) { + *count = strtoul(atts[i + 1], &p, 0); + if (*count == 0) + *variable = true; + } else if (strcmp(atts[i], "start") == 0) { + *offset = strtoul(atts[i + 1], &p, 0); + } else if (strcmp(atts[i], "size") == 0) { + *size = strtoul(atts[i + 1], &p, 0); + } + } + return; +} + +static struct v3d_group * +create_group(struct parser_context *ctx, + const char *name, + const char **atts, + struct v3d_group *parent) +{ + struct v3d_group *group; + + group = xzalloc(sizeof(*group)); + if (name) + group->name = xstrdup(name); + + group->spec = ctx->spec; + group->group_offset = 0; + group->group_count = 0; + group->variable = false; + + if (parent) { + group->parent = parent; + get_group_offset_count(atts, + &group->group_offset, + &group->group_count, + &group->group_size, + &group->variable); + } + + return group; +} + +static struct v3d_enum * +create_enum(struct parser_context *ctx, const char *name, const char **atts) +{ + struct v3d_enum *e; + + e = xzalloc(sizeof(*e)); + if (name) + e->name = xstrdup(name); + + e->nvalues = 0; + + return e; +} + +static void +get_register_offset(const char **atts, uint32_t *offset) +{ + char *p; + int i; + + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "num") == 0) + *offset = strtoul(atts[i + 1], &p, 0); + } + return; +} + +static void +get_start_end_pos(int *start, int *end) +{ + /* start value has to be mod with 32 as we need the relative + * start position in the first DWord. For the end position, add + * the length of the field to the start position to get the + * relative postion in the 64 bit address. + */ + if (*end - *start > 32) { + int len = *end - *start; + *start = *start % 32; + *end = *start + len; + } else { + *start = *start % 32; + *end = *end % 32; + } + + return; +} + +static inline uint64_t +mask(int start, int end) +{ + uint64_t v; + + v = ~0ULL >> (63 - end + start); + + return v << start; +} + +static inline uint64_t +field(uint64_t value, int start, int end) +{ + get_start_end_pos(&start, &end); + return (value & mask(start, end)) >> (start); +} + +static inline uint64_t +field_address(uint64_t value, int start, int end) +{ + /* no need to right shift for address/offset */ + get_start_end_pos(&start, &end); + return (value & mask(start, end)); +} + +static struct v3d_type +string_to_type(struct parser_context *ctx, const char *s) +{ + int i, f; + struct v3d_group *g; + struct v3d_enum *e; + + if (strcmp(s, "int") == 0) + return (struct v3d_type) { .kind = V3D_TYPE_INT }; + else if (strcmp(s, "uint") == 0) + return (struct v3d_type) { .kind = V3D_TYPE_UINT }; + else if (strcmp(s, "bool") == 0) + return (struct v3d_type) { .kind = V3D_TYPE_BOOL }; + else if (strcmp(s, "float") == 0) + return (struct v3d_type) { .kind = V3D_TYPE_FLOAT }; + else if (strcmp(s, "address") == 0) + return (struct v3d_type) { .kind = V3D_TYPE_ADDRESS }; + else if (strcmp(s, "offset") == 0) + return (struct v3d_type) { .kind = V3D_TYPE_OFFSET }; + else if (sscanf(s, "u%d.%d", &i, &f) == 2) + return (struct v3d_type) { .kind = V3D_TYPE_UFIXED, .i = i, .f = f }; + else if (sscanf(s, "s%d.%d", &i, &f) == 2) + return (struct v3d_type) { .kind = V3D_TYPE_SFIXED, .i = i, .f = f }; + else if (g = v3d_spec_find_struct(ctx->spec, s), g != NULL) + return (struct v3d_type) { .kind = V3D_TYPE_STRUCT, .v3d_struct = g }; + else if (e = v3d_spec_find_enum(ctx->spec, s), e != NULL) + return (struct v3d_type) { .kind = V3D_TYPE_ENUM, .v3d_enum = e }; + else if (strcmp(s, "mbo") == 0) + return (struct v3d_type) { .kind = V3D_TYPE_MBO }; + else + fail(&ctx->loc, "invalid type: %s", s); +} + +static struct v3d_field * +create_field(struct parser_context *ctx, const char **atts) +{ + struct v3d_field *field; + char *p; + int i; + uint32_t size = 0; + + field = xzalloc(sizeof(*field)); + + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "name") == 0) + field->name = xstrdup(atts[i + 1]); + else if (strcmp(atts[i], "start") == 0) { + field->start = strtoul(atts[i + 1], &p, 0); + if (is_byte_offset(atts[i + 1])) + field->start *= 8; + } else if (strcmp(atts[i], "end") == 0) { + field->end = strtoul(atts[i + 1], &p, 0) - 1; + if (is_byte_offset(atts[i + 1])) + field->end *= 8; + } else if (strcmp(atts[i], "size") == 0) { + size = strtoul(atts[i + 1], &p, 0); + if (is_byte_offset(atts[i + 1])) + size *= 8; + } else if (strcmp(atts[i], "type") == 0) + field->type = string_to_type(ctx, atts[i + 1]); + else if (strcmp(atts[i], "default") == 0) { + field->has_default = true; + field->default_value = strtoul(atts[i + 1], &p, 0); + } + } + + if (size) + field->end = field->start + size - 1; + + return field; +} + +static struct v3d_value * +create_value(struct parser_context *ctx, const char **atts) +{ + struct v3d_value *value = xzalloc(sizeof(*value)); + + for (int i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "name") == 0) + value->name = xstrdup(atts[i + 1]); + else if (strcmp(atts[i], "value") == 0) + value->value = strtoul(atts[i + 1], NULL, 0); + } + + return value; +} + +static void +create_and_append_field(struct parser_context *ctx, + const char **atts) +{ + if (ctx->group->nfields == ctx->group->fields_size) { + ctx->group->fields_size = MAX2(ctx->group->fields_size * 2, 2); + ctx->group->fields = + (struct v3d_field **) realloc(ctx->group->fields, + sizeof(ctx->group->fields[0]) * + ctx->group->fields_size); + } + + ctx->group->fields[ctx->group->nfields++] = create_field(ctx, atts); +} + +static void +set_group_opcode(struct v3d_group *group, const char **atts) +{ + char *p; + int i; + + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "code") == 0) + group->opcode = strtoul(atts[i + 1], &p, 0); + } + return; +} + +static void +start_element(void *data, const char *element_name, const char **atts) +{ + struct parser_context *ctx = data; + int i; + const char *name = NULL; + const char *ver = NULL; + + ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser); + + for (i = 0; atts[i]; i += 2) { + if (strcmp(atts[i], "name") == 0) + name = atts[i + 1]; + else if (strcmp(atts[i], "gen") == 0) + ver = atts[i + 1]; + } + + if (strcmp(element_name, "vcxml") == 0) { + if (ver == NULL) + fail(&ctx->loc, "no ver given"); + + int major, minor; + int n = sscanf(ver, "%d.%d", &major, &minor); + if (n == 0) + fail(&ctx->loc, "invalid ver given: %s", ver); + if (n == 1) + minor = 0; + + ctx->spec->ver = major * 10 + minor; + } else if (strcmp(element_name, "packet") == 0 || + strcmp(element_name, "struct") == 0) { + ctx->group = create_group(ctx, name, atts, NULL); + + if (strcmp(element_name, "packet") == 0) + set_group_opcode(ctx->group, atts); + } else if (strcmp(element_name, "register") == 0) { + ctx->group = create_group(ctx, name, atts, NULL); + get_register_offset(atts, &ctx->group->register_offset); + } else if (strcmp(element_name, "group") == 0) { + struct v3d_group *previous_group = ctx->group; + while (previous_group->next) + previous_group = previous_group->next; + + struct v3d_group *group = create_group(ctx, "", atts, + ctx->group); + previous_group->next = group; + ctx->group = group; + } else if (strcmp(element_name, "field") == 0) { + create_and_append_field(ctx, atts); + } else if (strcmp(element_name, "enum") == 0) { + ctx->enoom = create_enum(ctx, name, atts); + } else if (strcmp(element_name, "value") == 0) { + ctx->values[ctx->nvalues++] = create_value(ctx, atts); + assert(ctx->nvalues < ARRAY_SIZE(ctx->values)); + } + +} + +static void +end_element(void *data, const char *name) +{ + struct parser_context *ctx = data; + struct v3d_spec *spec = ctx->spec; + + if (strcmp(name, "packet") == 0 || + strcmp(name, "struct") == 0 || + strcmp(name, "register") == 0) { + struct v3d_group *group = ctx->group; + + ctx->group = ctx->group->parent; + + if (strcmp(name, "packet") == 0) { + spec->commands[spec->ncommands++] = group; + + /* V3D packet XML has the packet contents with offsets + * starting from the first bit after the opcode, to + * match the spec. Shift the fields up now. + */ + for (int i = 0; i < group->nfields; i++) { + group->fields[i]->start += 8; + group->fields[i]->end += 8; + } + } + else if (strcmp(name, "struct") == 0) + spec->structs[spec->nstructs++] = group; + else if (strcmp(name, "register") == 0) + spec->registers[spec->nregisters++] = group; + + assert(spec->ncommands < ARRAY_SIZE(spec->commands)); + assert(spec->nstructs < ARRAY_SIZE(spec->structs)); + assert(spec->nregisters < ARRAY_SIZE(spec->registers)); + } else if (strcmp(name, "group") == 0) { + ctx->group = ctx->group->parent; + } else if (strcmp(name, "field") == 0) { + assert(ctx->group->nfields > 0); + struct v3d_field *field = ctx->group->fields[ctx->group->nfields - 1]; + size_t size = ctx->nvalues * sizeof(ctx->values[0]); + field->inline_enum.values = xzalloc(size); + field->inline_enum.nvalues = ctx->nvalues; + memcpy(field->inline_enum.values, ctx->values, size); + ctx->nvalues = 0; + } else if (strcmp(name, "enum") == 0) { + struct v3d_enum *e = ctx->enoom; + size_t size = ctx->nvalues * sizeof(ctx->values[0]); + e->values = xzalloc(size); + e->nvalues = ctx->nvalues; + memcpy(e->values, ctx->values, size); + ctx->nvalues = 0; + ctx->enoom = NULL; + spec->enums[spec->nenums++] = e; + } +} + +static void +character_data(void *data, const XML_Char *s, int len) +{ +} + +static uint32_t zlib_inflate(const void *compressed_data, + uint32_t compressed_len, + void **out_ptr) +{ + struct z_stream_s zstream; + void *out; + + memset(&zstream, 0, sizeof(zstream)); + + zstream.next_in = (unsigned char *)compressed_data; + zstream.avail_in = compressed_len; + + if (inflateInit(&zstream) != Z_OK) + return 0; + + out = malloc(4096); + zstream.next_out = out; + zstream.avail_out = 4096; + + do { + switch (inflate(&zstream, Z_SYNC_FLUSH)) { + case Z_STREAM_END: + goto end; + case Z_OK: + break; + default: + inflateEnd(&zstream); + return 0; + } + + if (zstream.avail_out) + break; + + out = realloc(out, 2*zstream.total_out); + if (out == NULL) { + inflateEnd(&zstream); + return 0; + } + + zstream.next_out = (unsigned char *)out + zstream.total_out; + zstream.avail_out = zstream.total_out; + } while (1); + end: + inflateEnd(&zstream); + *out_ptr = out; + return zstream.total_out; +} + +struct v3d_spec * +v3d_spec_load(const struct v3d_device_info *devinfo) +{ + struct parser_context ctx; + void *buf; + uint8_t *text_data = NULL; + uint32_t text_offset = 0, text_length = 0, total_length; + + for (int i = 0; i < ARRAY_SIZE(genxml_files_table); i++) { + if (genxml_files_table[i].gen_10 == devinfo->ver) { + text_offset = genxml_files_table[i].offset; + text_length = genxml_files_table[i].length; + break; + } + } + + if (text_length == 0) { + fprintf(stderr, "unable to find gen (%u) data\n", devinfo->ver); + return NULL; + } + + memset(&ctx, 0, sizeof ctx); + ctx.parser = XML_ParserCreate(NULL); + XML_SetUserData(ctx.parser, &ctx); + if (ctx.parser == NULL) { + fprintf(stderr, "failed to create parser\n"); + return NULL; + } + + XML_SetElementHandler(ctx.parser, start_element, end_element); + XML_SetCharacterDataHandler(ctx.parser, character_data); + + ctx.spec = xzalloc(sizeof(*ctx.spec)); + + total_length = zlib_inflate(compress_genxmls, + sizeof(compress_genxmls), + (void **) &text_data); + assert(text_offset + text_length <= total_length); + + buf = XML_GetBuffer(ctx.parser, text_length); + memcpy(buf, &text_data[text_offset], text_length); + + if (XML_ParseBuffer(ctx.parser, text_length, true) == 0) { + fprintf(stderr, + "Error parsing XML at line %ld col %ld byte %ld/%u: %s\n", + XML_GetCurrentLineNumber(ctx.parser), + XML_GetCurrentColumnNumber(ctx.parser), + XML_GetCurrentByteIndex(ctx.parser), text_length, + XML_ErrorString(XML_GetErrorCode(ctx.parser))); + XML_ParserFree(ctx.parser); + free(text_data); + return NULL; + } + + XML_ParserFree(ctx.parser); + free(text_data); + + return ctx.spec; +} + +struct v3d_group * +v3d_spec_find_instruction(struct v3d_spec *spec, const uint8_t *p) +{ + uint8_t opcode = *p; + + for (int i = 0; i < spec->ncommands; i++) { + struct v3d_group *group = spec->commands[i]; + + if (opcode != group->opcode) + continue; + + /* If there's a "sub-id" field, make sure that it matches the + * instruction being decoded. + */ + struct v3d_field *subid = NULL; + for (int j = 0; j < group->nfields; j++) { + struct v3d_field *field = group->fields[j]; + if (strcmp(field->name, "sub-id") == 0) { + subid = field; + break; + } + } + + if (subid && (__gen_unpack_uint(p, subid->start, subid->end) != + subid->default_value)) { + continue; + } + + return group; + } + + return NULL; +} + +/** Returns the size of a V3D packet. */ +int +v3d_group_get_length(struct v3d_group *group) +{ + int last_bit = 0; + for (int i = 0; i < group->nfields; i++) { + struct v3d_field *field = group->fields[i]; + + last_bit = MAX2(last_bit, field->end); + } + return last_bit / 8 + 1; +} + +void +v3d_field_iterator_init(struct v3d_field_iterator *iter, + struct v3d_group *group, + const uint8_t *p, + bool print_colors) +{ + memset(iter, 0, sizeof(*iter)); + + iter->group = group; + iter->p = p; + iter->print_colors = print_colors; +} + +static const char * +v3d_get_enum_name(struct v3d_enum *e, uint64_t value) +{ + for (int i = 0; i < e->nvalues; i++) { + if (e->values[i]->value == value) { + return e->values[i]->name; + } + } + return NULL; +} + +static bool +iter_more_fields(const struct v3d_field_iterator *iter) +{ + return iter->field_iter < iter->group->nfields; +} + +static uint32_t +iter_group_offset_bits(const struct v3d_field_iterator *iter, + uint32_t group_iter) +{ + return iter->group->group_offset + (group_iter * + iter->group->group_size); +} + +static bool +iter_more_groups(const struct v3d_field_iterator *iter) +{ + if (iter->group->variable) { + return iter_group_offset_bits(iter, iter->group_iter + 1) < + (v3d_group_get_length(iter->group) * 8); + } else { + return (iter->group_iter + 1) < iter->group->group_count || + iter->group->next != NULL; + } +} + +static void +iter_advance_group(struct v3d_field_iterator *iter) +{ + if (iter->group->variable) + iter->group_iter++; + else { + if ((iter->group_iter + 1) < iter->group->group_count) { + iter->group_iter++; + } else { + iter->group = iter->group->next; + iter->group_iter = 0; + } + } + + iter->field_iter = 0; +} + +static bool +iter_advance_field(struct v3d_field_iterator *iter) +{ + while (!iter_more_fields(iter)) { + if (!iter_more_groups(iter)) + return false; + + iter_advance_group(iter); + } + + iter->field = iter->group->fields[iter->field_iter++]; + if (iter->field->name) + strncpy(iter->name, iter->field->name, sizeof(iter->name)); + else + memset(iter->name, 0, sizeof(iter->name)); + iter->offset = iter_group_offset_bits(iter, iter->group_iter) / 8 + + iter->field->start / 8; + iter->struct_desc = NULL; + + return true; +} + +bool +v3d_field_iterator_next(struct v3d_field_iterator *iter) +{ + if (!iter_advance_field(iter)) + return false; + + const char *enum_name = NULL; + + int s = iter->field->start; + int e = iter->field->end; + + switch (iter->field->type.kind) { + case V3D_TYPE_UNKNOWN: + case V3D_TYPE_INT: { + uint32_t value = __gen_unpack_sint(iter->p, s, e); + snprintf(iter->value, sizeof(iter->value), "%d", value); + enum_name = v3d_get_enum_name(&iter->field->inline_enum, value); + break; + } + case V3D_TYPE_UINT: { + uint32_t value = __gen_unpack_uint(iter->p, s, e); + snprintf(iter->value, sizeof(iter->value), "%u", value); + enum_name = v3d_get_enum_name(&iter->field->inline_enum, value); + break; + } + case V3D_TYPE_BOOL: { + const char *true_string = + iter->print_colors ? "\e[0;35mtrue\e[0m" : "true"; + snprintf(iter->value, sizeof(iter->value), "%s", + __gen_unpack_uint(iter->p, s, e) ? + true_string : "false"); + break; + } + case V3D_TYPE_FLOAT: + snprintf(iter->value, sizeof(iter->value), "%f", + __gen_unpack_float(iter->p, s, e)); + break; + case V3D_TYPE_ADDRESS: + case V3D_TYPE_OFFSET: + snprintf(iter->value, sizeof(iter->value), "0x%08"PRIx64, + __gen_unpack_uint(iter->p, s, e) << (31 - (e - s))); + break; + case V3D_TYPE_STRUCT: + snprintf(iter->value, sizeof(iter->value), "<struct %s>", + iter->field->type.v3d_struct->name); + iter->struct_desc = + v3d_spec_find_struct(iter->group->spec, + iter->field->type.v3d_struct->name); + break; + case V3D_TYPE_SFIXED: + snprintf(iter->value, sizeof(iter->value), "%f", + __gen_unpack_sfixed(iter->p, s, e, + iter->field->type.f)); + break; + case V3D_TYPE_UFIXED: + snprintf(iter->value, sizeof(iter->value), "%f", + __gen_unpack_ufixed(iter->p, s, e, + iter->field->type.f)); + break; + case V3D_TYPE_MBO: + break; + case V3D_TYPE_ENUM: { + uint32_t value = __gen_unpack_uint(iter->p, s, e); + snprintf(iter->value, sizeof(iter->value), "%d", value); + enum_name = v3d_get_enum_name(iter->field->type.v3d_enum, value); + break; + } + } + + if (strlen(iter->group->name) == 0) { + int length = strlen(iter->name); + snprintf(iter->name + length, sizeof(iter->name) - length, + "[%i]", iter->group_iter); + } + + if (enum_name) { + int length = strlen(iter->value); + snprintf(iter->value + length, sizeof(iter->value) - length, + " (%s)", enum_name); + } + + return true; +} + +void +v3d_print_group(FILE *outfile, struct v3d_group *group, + uint64_t offset, const uint8_t *p, bool color) +{ + struct v3d_field_iterator iter; + + v3d_field_iterator_init(&iter, group, p, color); + while (v3d_field_iterator_next(&iter)) { + fprintf(outfile, " %s: %s\n", iter.name, iter.value); + if (iter.struct_desc) { + uint64_t struct_offset = offset + iter.offset; + v3d_print_group(outfile, iter.struct_desc, + struct_offset, + &p[iter.offset], color); + } + } +} diff --git a/lib/mesa/src/broadcom/cle/v3d_decoder.h b/lib/mesa/src/broadcom/cle/v3d_decoder.h new file mode 100644 index 000000000..541d877a9 --- /dev/null +++ b/lib/mesa/src/broadcom/cle/v3d_decoder.h @@ -0,0 +1,146 @@ +/* + * Copyright © 2016 Intel Corporation + * Copyright © 2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 V3D_DECODER_H +#define V3D_DECODER_H + +#include <stdint.h> +#include <stdio.h> +#include <stdbool.h> + +#include "broadcom/common/v3d_device_info.h" + +struct v3d_spec; +struct v3d_group; +struct v3d_field; + +struct v3d_group *v3d_spec_find_struct(struct v3d_spec *spec, const char *name); +struct v3d_spec *v3d_spec_load(const struct v3d_device_info *devinfo); +struct v3d_group *v3d_spec_find_instruction(struct v3d_spec *spec, const uint8_t *p); +struct v3d_group *v3d_spec_find_register(struct v3d_spec *spec, uint32_t offset); +struct v3d_group *v3d_spec_find_register_by_name(struct v3d_spec *spec, const char *name); +int v3d_group_get_length(struct v3d_group *group); +const char *v3d_group_get_name(struct v3d_group *group); +uint8_t v3d_group_get_opcode(struct v3d_group *group); +struct v3d_enum *v3d_spec_find_enum(struct v3d_spec *spec, const char *name); + +struct v3d_field_iterator { + struct v3d_group *group; + char name[128]; + char value[128]; + struct v3d_group *struct_desc; + const uint8_t *p; + int offset; /**< current field starts at &p[offset] */ + + int field_iter; + int group_iter; + + struct v3d_field *field; + bool print_colors; +}; + +struct v3d_group { + struct v3d_spec *spec; + char *name; + + struct v3d_field **fields; + uint32_t nfields; + uint32_t fields_size; + + uint32_t group_offset, group_count; + uint32_t group_size; + bool variable; + + struct v3d_group *parent; + struct v3d_group *next; + + uint8_t opcode; + + /* Register specific */ + uint32_t register_offset; +}; + +struct v3d_value { + char *name; + uint64_t value; +}; + +struct v3d_enum { + char *name; + int nvalues; + struct v3d_value **values; +}; + +struct v3d_type { + enum { + V3D_TYPE_UNKNOWN, + V3D_TYPE_INT, + V3D_TYPE_UINT, + V3D_TYPE_BOOL, + V3D_TYPE_FLOAT, + V3D_TYPE_ADDRESS, + V3D_TYPE_OFFSET, + V3D_TYPE_STRUCT, + V3D_TYPE_UFIXED, + V3D_TYPE_SFIXED, + V3D_TYPE_MBO, + V3D_TYPE_ENUM + } kind; + + /* Struct definition for V3D_TYPE_STRUCT */ + union { + struct v3d_group *v3d_struct; + struct v3d_enum *v3d_enum; + struct { + /* Integer and fractional sizes for V3D_TYPE_UFIXED and + * V3D_TYPE_SFIXED + */ + int i, f; + }; + }; +}; + +struct v3d_field { + char *name; + int start, end; + struct v3d_type type; + bool has_default; + uint32_t default_value; + + struct v3d_enum inline_enum; +}; + +void v3d_field_iterator_init(struct v3d_field_iterator *iter, + struct v3d_group *group, + const uint8_t *p, + bool print_colors); + +bool v3d_field_iterator_next(struct v3d_field_iterator *iter); + +void v3d_print_group(FILE *out, + struct v3d_group *group, + uint64_t offset, const uint8_t *p, + bool color); + +#endif /* V3D_DECODER_H */ diff --git a/lib/mesa/src/broadcom/cle/v3d_packet_v33.xml b/lib/mesa/src/broadcom/cle/v3d_packet_v33.xml new file mode 100644 index 000000000..e6562a262 --- /dev/null +++ b/lib/mesa/src/broadcom/cle/v3d_packet_v33.xml @@ -0,0 +1,910 @@ +<vcxml gen="3.3"> + + <enum name="Compare Function" prefix="V3D_COMPARE_FUNC"> + <value name="NEVER" value="0"/> + <value name="LESS" value="1"/> + <value name="EQUAL" value="2"/> + <value name="LEQUAL" value="3"/> + <value name="GREATER" value="4"/> + <value name="NOTEQUAL" value="5"/> + <value name="GEQUAL" value="6"/> + <value name="ALWAYS" value="7"/> + </enum> + + <enum name="Blend Factor" prefix="V3D_BLEND_FACTOR"> + <value name="ZERO" value="0"/> + <value name="ONE" value="1"/> + <value name="SRC_COLOR" value="2"/> + <value name="INV_SRC_COLOR" value="3"/> + <value name="DST_COLOR" value="4"/> + <value name="INV_DST_COLOR" value="5"/> + <value name="SRC_ALPHA" value="6"/> + <value name="INV_SRC_ALPHA" value="7"/> + <value name="DST_ALPHA" value="8"/> + <value name="INV_DST_ALPHA" value="9"/> + <value name="CONST_COLOR" value="10"/> + <value name="INV_CONST_COLOR" value="11"/> + <value name="CONST_ALPHA" value="12"/> + <value name="INV_CONST_ALPHA" value="13"/> + <value name="SRC_ALPHA_SATURATE" value="14"/> + </enum> + + <enum name="Blend Mode" prefix="V3D_BLEND_MODE"> + <value name="ADD" value="0"/> + <value name="SUB" value="1"/> + <value name="RSUB" value="2"/> + <value name="MIN" value="3"/> + <value name="MAX" value="4"/> + <value name="MUL" value="5"/> + <value name="SCREEN" value="6"/> + <value name="DARKEN" value="7"/> + <value name="LIGHTEN" value="8"/> + </enum> + + <enum name="Stencil Op" prefix="V3D_STENCIL_OP"> + <value name="ZERO" value="0"/> + <value name="KEEP" value="1"/> + <value name="REPLACE" value="2"/> + <value name="INCR" value="3"/> + <value name="DECR" value="4"/> + <value name="INVERT" value="5"/> + <value name="INCWRAP" value="6"/> + <value name="DECWRAP" value="7"/> + </enum> + + <enum name="Primitive" prefix="V3D_PRIM"> + <value name="POINTS" value="0"/> + <value name="LINES" value="1"/> + <value name="LINE_LOOP" value="2"/> + <value name="LINE_STRIP" value="3"/> + <value name="TRIANGLES" value="4"/> + <value name="TRIANGLE_STRIP" value="5"/> + <value name="TRIANGLE_FAN" value="6"/> + <value name="POINTS_TF" value="16"/> + <value name="LINES_TF" value="17"/> + <value name="LINE_LOOP_TF" value="18"/> + <value name="LINE_STRIP_TF" value="19"/> + <value name="TRIANGLES_TF" value="20"/> + <value name="TRIANGLE_STRIP_TF" value="21"/> + <value name="TRIANGLE_FAN_TF" value="22"/> + </enum> + + <packet code="0" name="Halt"/> + <packet code="1" name="NOP"/> + <packet code="4" name="Flush"/> + <packet code="5" name="Flush All State"/> + <packet code="6" name="Start Tile Binning"/> + <packet code="7" name="Increment Semaphore"/> + <packet code="8" name="Wait on Semaphore"/> + <packet code="9" name="Wait for previous frame"/> + <packet code="10" name="Enable Z-only rendering" cl="R"/> + <packet code="11" name="Disable Z-only rendering" cl="R"/> + <packet code="12" name="End of Z-only rendering in frame"/> + <packet code="13" name="End of rendering"/> + + <packet code="14" name="Wait for transform feedback" cl="B"> + <field name="Block count" size="8" start="0" type="uint"/> + </packet> + + <packet code="15" name="Branch to auto-chained sub-list"> + <field name="address" size="32" start="0" type="address"/> + </packet> + + <packet code="16" name="Branch"> + <field name="address" size="32" start="0" type="address"/> + </packet> + + <packet code="17" name="Branch to Sub-list"> + <field name="address" size="32" start="0" type="address"/> + </packet> + + <packet code="18" name="Return from sub-list"/> + <packet code="19" name="Flush VCD cache"/> + + <packet code="20" name="Start Address of Generic Tile List"> + <field name="start" size="32" start="0" type="address"/> + <field name="end" size="32" start="32" type="address"/> + </packet> + + <packet code="21" name="Branch to Implicit Tile List"> + <field name="tile list set number" size="8" start="0" type="uint"/> + </packet> + + <packet code="22" name="Branch to Explicit Supertile"> + <field name="Absolute address of explicit supertile render list" size="32" start="24" type="address"/> + <field name="explicit supertile number" size="8" start="16" type="uint"/> + <field name="row number" size="8" start="8" type="uint"/> + <field name="column number" size="8" start="0" type="uint"/> + </packet> + + <packet code="23" name="Supertile Coordinates"> + <field name="row number in supertiles" size="8" start="8" type="uint"/> + <field name="column number in supertiles" size="8" start="0" type="uint"/> + </packet> + + <packet code="24" name="Store Multi-Sample Resolved Tile Color Buffer" cl="R"/> + + <packet code="25" name="Store Multi-Sample Resolved Tile Color Buffer (extended)" cl="R"> + <field name="Disable Color Buffer write" size="8" start="8" type="uint"/> + <field name="Enable Z write" size="1" start="7" type="bool"/> + <field name="Enable Stencil write" size="1" start="6" type="bool"/> + <!-- bit 5 unused --> + <field name="Disable Colour buffer(s) clear on write" size="1" start="4" type="bool"/> + <field name="Disable Stencil buffer clear on write" size="1" start="3" type="bool"/> + <field name="Disable Z buffer clear on write" size="1" start="2" type="bool"/> + <field name="Disable fast opportunistic write out in multisample mode" size="1" start="1" type="bool"/> + <field name="Last Tile of Frame" size="1" start="0" type="bool"/> + </packet> + + <packet code="26" name="Reload Tile Colour Buffer" cl="R"> + <field name="Disable Colour Buffer load" size="8" start="8" type="uint"/> + <field name="Enable Z load" size="1" start="7" type="bool"/> + <field name="Enable Stencil load" size="1" start="6" type="bool"/> + </packet> + + <packet code="27" name="End of Tile Marker" cl="R"/> + + <packet code="29" name="Store Tile Buffer General" cl="R"> + <field name="Address" size="32" start="16" type="address"/> + <field name="Padded height of output image in UIF blocks" size="13" start="11" type="uint"/> + <field name="XOR UIF" size="1" start="10" type="bool"/> + <field name="Last Tile of Frame" size="1" start="8" type="bool"/> + <field name="Disable Colour buffer(s) clear on write" size="1" start="7" type="bool"/> + <field name="Disable Stencil buffer clear on write" size="1" start="6" type="bool"/> + <field name="Disable Z buffer clear on write" size="1" start="5" type="bool"/> + <field name="Raw Mode" size="1" start="4" type="bool"/> + <field name="Buffer to Store" size="4" start="0" type="uint"> + <value name="Render target 0" value="0"/> + <value name="Render target 1" value="1"/> + <value name="Render target 2" value="2"/> + <value name="Render target 3" value="3"/> + <value name="None" value="8"/> + <value name="Z" value="9"/> + <value name="Stencil" value="10"/> + <value name="Z+Stencil" value="11"/> + </field> + </packet> + + <packet code="30" name="Load Tile Buffer General" cl="R"> + <field name="Address" size="24" start="24" type="address"/> + <field name="Padded height of output image in UIF blocks" size="13" start="11" type="uint"/> + <field name="XOR UIF" size="1" start="10" type="bool"/> + <field name="Raw Mode" size="1" start="4" type="bool"/> + <field name="Buffer to Load" size="4" start="0" type="uint"> + <value name="Render target 0" value="0"/> + <value name="Render target 1" value="1"/> + <value name="Render target 2" value="2"/> + <value name="Render target 3" value="3"/> + <value name="None" value="8"/> + <value name="Z" value="9"/> + <value name="Stencil" value="10"/> + <value name="Z+Stencil" value="11"/> + </field> + </packet> + + <packet code="32" name="Indexed Primitive List" cl="B"> + <field name="Minimum index" size="32" start="104" type="uint"/> + <field name="Enable Primitive Restarts" size="1" start="103" type="bool"/> + <field name="Maximum index" size="31" start="72" type="uint"/> + <field name="Address of Indices List" size="32" start="40" type="address"/> + <field name="Length" size="32" start="8" type="uint"/> + + <field name="Index type" size="2" start="6" type="uint"> + <value name="Index type 8-bit" value="0"/> + <value name="Index type 16-bit" value="1"/> + <value name="Index type 32-bit" value="2"/> + </field> + + <field name="mode" size="5" start="0" type="uint"> + </field> + </packet> + + <packet code="34" name="Indexed Instanced Primitive List" cl="B"> + <field name="Enable Primitive Restarts" size="1" start="135" type="bool"/> + <field name="Maximum index" size="31" start="104" type="uint"/> + <field name="Address of Indices List" size="32" start="72" type="address"/> + <field name="Number of Instances" size="32" start="40" type="uint"/> + <field name="Instance Length" size="32" start="8" type="uint"/> + + <field name="Index type" size="2" start="6" type="uint"> + <value name="Index type 8-bit" value="0"/> + <value name="Index type 16-bit" value="1"/> + <value name="Index type 32-bit" value="2"/> + </field> + + <field name="mode" size="5" start="0" type="Primitive"/> + </packet> + + <packet code="36" name="Vertex Array Primitives" cl="B"> + <field name="Index of First Vertex" size="32" start="40" type="uint"/> + <field name="Length" size="32" start="8" type="uint"/> + + <field name="mode" size="8" start="0" type="Primitive"/> + </packet> + + <packet code="38" name="Vertex Array Instanced Primitives" cl="B"> + <field name="Index of First Vertex" size="32" start="72" type="uint"/> + <field name="Number of Instances" size="32" start="40" type="uint"/> + <field name="Instance Length" size="32" start="8" type="uint"/> + + <field name="mode" size="8" start="0" type="Primitive"/> + </packet> + + <packet code="43" name="Base Vertex Base Instance" cl="B"> + <field name="Base Instance" size="32" start="32" type="uint"/> + + <field name="Base Vertex" size="32" start="0" type="uint"/> + </packet> + + <packet code="56" name="Primitive List Format"> + <field name="data type" size="1" start="6" type="uint"> + <value name="List Indexed" value="0"/> + <value name="List 32-bit X/Y" value="1"/> + </field> + <field name="primitive type" size="6" start="0" type="uint"> + <value name="List Points" value="0"/> + <value name="List Lines" value="1"/> + <value name="List Triangles" value="2"/> + </field> + </packet> + + <packet code="64" name="GL Shader State"> + <field name="address" size="27" start="5" type="address"/> + <field name="number of attribute arrays" size="5" start="0" type="uint"/> + </packet> + + <packet code="74" name="Transform Feedback Enable"> + <field name="number of 32-bit Output Buffer Address following" size="3" start="8" type="uint"/> + <field name="number of 16-bit Output Data Specs following" size="5" start="11" type="uint"/> + </packet> + + <packet code="75" name="Flush Transform Feedback Data"/> + + <struct name="Transform Feedback Output Data Spec"> + <field name="First Shaded Vertex Value to output" size="8" start="0" type="uint"/> + <field name="Number of consecutive Vertex Values to output as 32-bit values minus 1" size="4" start="8" type="uint"/> + <field name="Output Buffer to write to" size="2" start="12" type="uint"/> + </struct> + + <struct name="Transform Feedback Output Address"> + <field name="address" size="32" start="0" type="address"/> + </struct> + + <packet code="80" name="Stencil Config"> + <field name="Stencil Write Mask" size="8" start="32" type="uint"/> + <field name="Back Config" size="1" start="29" type="bool"/> + <field name="Front Config" size="1" start="28" type="bool"/> + <field name="Stencil Pass Op" size="3" start="25" type="Stencil Op"/> + <field name="Depth Test Fail Op" size="3" start="22" type="Stencil Op"/> + <field name="Stencil Test Fail Op" size="3" start="19" type="Stencil Op"/> + <field name="Stencil Test Function" size="3" start="16" type="Compare Function"/> + <field name="Stencil Test Mask" size="8" start="8" type="uint"/> + <field name="Stencil Ref Value" size="8" start="0" type="uint"/> + </packet> + + <packet code="84" name="Blend Config"> + <field name="VG Coverage Modes" size="2" start="28" type="uint"/> + <field name="Colour blend dst factor" size="4" start="20" type="Blend Factor"/> + <field name="Colour blend src factor" size="4" start="16" type="Blend Factor"/> + <field name="Colour blend mode" size="4" start="12" type="Blend Mode"/> + <field name="Alpha blend dst factor" size="4" start="8" type="Blend Factor"/> + <field name="Alpha blend src factor" size="4" start="4" type="Blend Factor"/> + <field name="Alpha blend mode" size="4" start="0" type="Blend Mode"/> + </packet> + + <packet code="86" name="Blend Constant Colour"> + <field name="Alpha (F16)" size="16" start="48" type="uint"/> + <field name="Blue (F16)" size="16" start="32" type="uint"/> + <field name="Green (F16)" size="16" start="16" type="uint"/> + <field name="Red (F16)" size="16" start="0" type="uint"/> + </packet> + + <packet code="87" name="Colour Write Masks"> + <field name="Reserved" size="16" start="16" type="uint"/> + <field name="Render Target 3 per colour component write masks" size="4" start="12" type="uint"/> + <field name="Render Target 2 per colour component write masks" size="4" start="8" type="uint"/> + <field name="Render Target 1 per colour component write masks" size="4" start="4" type="uint"/> + <field name="Render Target 0 per colour component write masks" size="4" start="0" type="uint"/> + </packet> + + <packet code="96" name="Configuration Bits"> + <field name="Direct3D Provoking Vertex" size="1" start="21" type="bool"/> + <field name="Direct3D 'Point-fill' mode" size="1" start="20" type="bool"/> + <field name="Blend enable" size="1" start="19" type="bool"/> + <field name="Stencil enable" size="1" start="18" type="bool"/> + <field name="Early Z updates enable" size="1" start="17" type="bool"/> + <field name="Early Z enable" size="1" start="16" type="bool"/> + <field name="Z updates enable" size="1" start="15" type="bool"/> + <field name="Depth-Test Function" size="3" start="12" type="Compare Function"/> + <field name="Direct3D Wireframe triangles mode" size="1" start="11" type="bool"/> + <field name="Coverage Update Mode" size="2" start="9" type="uint"/> + <field name="Coverage Pipe Select" size="1" start="8" type="bool"/> + <field name="Rasterizer Oversample Mode" size="2" start="6" type="uint"/> + <field name="Line Rasterization" size="2" start="4" type="uint"/> + <field name="Enable Depth Offset" size="1" start="3" type="bool"/> + <field name="Clockwise Primitives" size="1" start="2" type="bool"/> + <field name="Enable Reverse Facing Primitive" size="1" start="1" type="bool"/> + <field name="Enable Forward Facing Primitive" size="1" start="0" type="bool"/> + </packet> + + <packet code="97" name="Zero All Flat Shade Flags"/> + + <packet code="98" name="Flat Shade Flags"> + <field name="Flat Shade Flags for varyings V0*24" size="24" start="8" type="uint"/> + <field name="Action for Flat Shade Flags of higher numbered varyings" size="2" start="6" type="uint"/> + <field name="Action for Flat Shade Flags of lower numbered varyings" size="2" start="4" type="uint"/> + <field name="Varying offset V0" size="4" start="0" type="uint"/> + </packet> + + <packet code="104" name="Point size"> + <field name="Point Size" size="32" start="0" type="float"/> + </packet> + + <packet code="105" name="Line width"> + <field name="Line width" size="32" start="0" type="float"/> + </packet> + + <packet name="Depth Offset" code="106"> + <!-- these fields are both float-1-8-7 encoded (top 16 bits of a float32) --> + <field name="Depth Offset Units" size="16" start="16" type="uint"/> + <field name="Depth Offset Factor" size="16" start="0" type="uint"/> + </packet> + + <packet name="Clip Window" code="107"> + <field name="Clip Window Height in pixels" size="16" start="48" type="uint"/> + <field name="Clip Window Width in pixels" size="16" start="32" type="uint"/> + <field name="Clip Window Bottom Pixel Coordinate" size="16" start="16" type="uint"/> + <field name="Clip Window Left Pixel Coordinate" size="16" start="0" type="uint"/> + </packet> + + <packet name="Viewport Offset" code="108"> + <field name="Viewport Centre Y-coordinate" size="32" start="32" type="s24.8"/> + <field name="Viewport Centre X-coordinate" size="32" start="0" type="s24.8"/> + </packet> + + <packet name="Clipper Z min/max clipping planes" code="109"> + <field name="Maximum Zw" size="32" start="32" type="float"/> + <field name="Minimum Zw" size="32" start="0" type="float"/> + </packet> + + <packet name="Clipper XY Scaling" code="110" cl="B"> + <field name="Viewport Half-Height in 1/256th of pixel" size="32" start="32" type="float"/> + <field name="Viewport Half-Width in 1/256th of pixel" size="32" start="0" type="float"/> + </packet> + + <packet name="Clipper Z Scale and Offset" code="111" cl="B"> + <field name="Viewport Z Offset (Zc to Zs)" size="32" start="32" type="float"/> + <field name="Viewport Z Scale (Zc to Zs)" size="32" start="0" type="float"/> + </packet> + + <packet code="120" name="Tile Binning Mode Configuration (Part1)"> + <field name="Double-buffer in non-ms mode" size="1" start="63" type="bool"/> + <field name="Multisample Mode (4x)" size="1" start="62" type="bool"/> + + <field name="Maximum BPP of all render targets" size="2" start="60" type="uint"> + <value name="Render target maximum 32bpp" value="0"/> + <value name="Render target maximum 64bpp" value="1"/> + <value name="Render target maximum 128bpp" value="2"/> + </field> + + <field name="Number of Render Targets" size="4" start="56" type="uint"/> + <field name="Height (in tiles)" size="12" start="44" type="uint"/> + <field name="Width (in tiles)" size="12" start="32" type="uint"/> + + <field name="Tile State Data Array Base Address" size="32" start="0" type="address"/> + + <field name="tile allocation block size" size="2" start="4" type="uint"> + <value name="tile allocation block size 64b" value="0"/> + <value name="tile allocation block size 128b" value="1"/> + <value name="tile allocation block size 256b" value="2"/> + </field> + <field name="tile allocation initial block size" size="2" start="2" type="uint"> + <value name="tile allocation initial block size 64b" value="0"/> + <value name="tile allocation initial block size 128b" value="1"/> + <value name="tile allocation initial block size 256b" value="2"/> + </field> + <field name="auto-initialize tile state data array" size="1" start="1" type="bool" default="1"/> + <field name="sub-id" size="1" start="0" type="uint" default="0"/> + </packet> + + <packet code="120" name="Tile Binning Mode Configuration (Part2)" cl="B"> + <field name="Tile Allocation Memory Address" size="32" start="32" type="address"/> + <field name="Tile Allocation Memory Size" size="32" start="0" type="uint"/> + + <field name="sub-id" size="1" start="0" type="uint" default="1"/> + </packet> + + <packet code="121" name="Tile Rendering Mode Configuration (Common Configuration)" cl="R"> + <field name="Disable Render Target Stores" size="8" start="56" type="uint"/> + <field name="Enable Z Store" size="1" start="55" type="bool"/> + <field name="Enable Stencil Store" size="1" start="54" type="bool"/> + + <field name="Early-Z disable" size="1" start="46" type="bool"/> + + <field name="Early-Z Test and Update Direction" size="1" start="45" type="uint"> + <value name="Early-Z direction LT/LE" value="0"/> + <value name="Early-Z direction GT/GE" value="1"/> + </field> + + <field name="Select Coverage Mode" size="1" start="44" type="bool"/> + <field name="Double-buffer in non-ms mode" size="1" start="43" type="bool"/> + <field name="Multisample Mode (4x)" size="1" start="42" type="bool"/> + + <field name="Maximum BPP of all render targets" size="2" start="40" type="uint"> + <value name="Render target maximum 32bpp" value="0"/> + <value name="Render target maximum 64bpp" value="1"/> + <value name="Render target maximum 128bpp" value="2"/> + </field> + + <field name="Image Height (pixels)" size="16" start="24" type="uint"/> + <field name="Image Width (pixels)" size="16" start="8" type="uint"/> + <field name="Number of Render Targets Minus 1" size="4" start="4" type="uint"/> + + <field name="sub-id" size="4" start="0" type="uint" default="0"/> + </packet> + + <packet code="121" name="Tile Rendering Mode Configuration (Render Target config)" cl="R"> + <field name="Address" size="32" start="32" type="address"/> + + <field name="Pad" size="4" start="28" type="uint"/> + + <field name="Flip Y" size="1" start="27" type="bool"/> + + <field name="Memory Format" size="3" start="24" type="uint" prefix="Memory Format"> + <value name="Raster" value="0"/> + <value name="Lineartile" value="1"/> + <value name="UB-linear (1 UIF block wide)" value="2"/> + <value name="UB-linear (2 UIF blocks wide)" value="3"/> + <value name="UIF (No XOR)" value="4"/> + <value name="UIF (XOR)" value="5"/> + </field> + + <field name="A dithered" size="1" start="23" type="bool"/> + <field name="BGR dithered" size="1" start="22" type="bool"/> + + <field name="Output image format" size="6" start="16" type="uint" prefix="Output Image Format"> + <value name="srgb8_alpha8" value="0"/> + <value name="srgb" value="1"/> + <value name="rgb10_a2ui" value="2"/> + <value name="rgb10_a2" value="3"/> + <value name="abgr1555" value="4"/> + <value name="alpha-masked abgr1555" value="5"/> + <value name="abgr4444" value="6"/> + <value name="bgr565" value="7"/> + <value name="r11f_g11f_b10f" value="8"/> + <value name="rgba32f" value="9"/> + <value name="rg32f" value="10"/> + <value name="r32f" value="11"/> + <value name="rgba32i" value="12"/> + <value name="rg32i" value="13"/> + <value name="r32i" value="14"/> + <value name="rgba32ui" value="15"/> + <value name="rg32ui" value="16"/> + <value name="r32ui" value="17"/> + <value name="rgba16f" value="18"/> + <value name="rg16f" value="19"/> + <value name="r16f" value="20"/> + <value name="rgba16i" value="21"/> + <value name="rg16i" value="22"/> + <value name="r16i" value="23"/> + <value name="rgba16ui" value="24"/> + <value name="rg16ui" value="25"/> + <value name="r16ui" value="26"/> + <value name="rgba8" value="27"/> + <value name="rgb8" value="28"/> + <value name="rg8" value="29"/> + <value name="r8" value="30"/> + <value name="rgba8i" value="31"/> + <value name="rg8i" value="32"/> + <value name="r8i" value="33"/> + <value name="rgba8ui" value="34"/> + <value name="rg8ui" value="35"/> + <value name="r8ui" value="36"/> + <value name="srgbx8" value="37"/> + <value name="rgbx8" value="38"/> + </field> + + <field name="Decimate mode" size="2" start="14" type="uint"/> + + <field name="Internal Type" size="4" start="10" type="uint" prefix="Internal Type"> + <value name="8i" value="0"/> + <value name="8ui" value="1"/> + <value name="8" value="2"/> + <value name="16i" value="4"/> + <value name="16ui" value="5"/> + <value name="16f" value="6"/> + <value name="32i" value="8"/> + <value name="32ui" value="9"/> + <value name="32f" value="10"/> + </field> + + <field name="Internal BPP" size="2" start="8" type="uint" prefix="Internal Bpp"> + <value name="32" value="0"/> + <value name="64" value="1"/> + <value name="128" value="2"/> + </field> + <field name="Render Target Number" size="4" start="4" type="uint"/> + <field name="sub-id" size="4" start="0" type="uint" default="2"/> + </packet> + + <packet code="121" name="Tile Rendering Mode Configuration (Z/Stencil config)" cl="R"> + <field name="Address" size="32" start="32" type="address"/> + + <field name="Padded height of output image in UIF blocks" size="13" start="25" type="uint"/> + + <field name="Memory Format" size="3" start="22" type="uint" prefix="Memory Format"> + <value name="Raster" value="0"/> + <value name="Lineartile" value="1"/> + <value name="UB-linear (1 UIF block wide)" value="2"/> + <value name="UB-linear (2 UIF blocks wide)" value="3"/> + <value name="UIF (No XOR)" value="4"/> + <value name="UIF (XOR)" value="5"/> + </field> + + <field name="Output image format" size="6" start="16" type="uint" prefix="Output Image Format"> + <value name="depth_component32f" value="0"/> + <value name="depth_component24" value="1"/> + <value name="depth_component16" value="2"/> + <value name="depth24_stencil8" value="3"/> + </field> + + <field name="Decimate mode" size="2" start="14" type="uint"/> + + <field name="Internal Type" size="4" start="10" type="uint" prefix="Internal Type"> + <value name="depth_32f" value="0"/> + <value name="depth_24" value="1"/> + <value name="depth_16" value="2"/> + </field> + + <field name="Internal BPP (ignored)" size="2" start="8" type="uint"/> + <!-- selects between Z/Stencil config packet and Separate Stencil packet. --> + <field name="Z/Stencil ID" size="4" start="4" type="uint" default="0"/> + <field name="sub-id" size="4" start="0" type="uint" default="1"/> + </packet> + + <packet code="121" name="Tile Rendering Mode Configuration (Z Stencil Clear Values)" cl="R"> + <field name="unused" size="16" start="48" type="uint"/> + + <field name="Z Clear Value" size="32" start="16" type="float"/> + + <field name="Stencil/VG Mask Clear Value" size="8" start="8" type="uint"/> + <field name="sub-id" size="4" start="0" type="uint" default="3"/> + </packet> + + <packet code="121" name="Tile Rendering Mode Configuration (Clear Colors Part1)" cl="R"> + <!-- Express this as a 56-bit field? --> + <field name="Clear Color next 24 bits" size="24" start="40" type="uint"/> + <field name="Clear Color low 32 bits" size="32" start="8" type="uint"/> + + <field name="Render Target number" size="4" start="4" type="uint"/> + <field name="sub-id" size="4" start="0" type="uint" default="4"/> + </packet> + + <packet code="121" name="Tile Rendering Mode Configuration (Clear Colors Part2)" cl="R"> + <!-- Express this as a 56-bit field? --> + <field name="Clear Color mid-high 24 bits" size="24" start="40" type="uint"/> + <field name="Clear Color mid-low 32 bits" size="32" start="8" type="uint"/> + + <field name="Render Target number" size="4" start="4" type="uint"/> + <field name="sub-id" size="4" start="0" type="uint" default="5"/> + </packet> + + <packet code="121" name="Tile Rendering Mode Configuration (Clear Colors Part3)" cl="R"> + <field name="pad" size="11" start="53" type="uint"/> + <field name="UIF padded height in UIF blocks" size="13" start="40" type="uint"/> + <!-- image height is for Y flipping --> + <field name="Raster Row Stride or Image Height in Pixels" size="16" start="24" type="uint"/> + <field name="Clear Color high 16 bits" size="16" start="8" type="uint"/> + + <field name="Render Target number" size="4" start="4" type="uint"/> + <field name="sub-id" size="4" start="0" type="uint" default="6"/> + </packet> + + <packet code="124" name="Tile Coordinates"> + <field name="tile row number" size="12" start="12" type="uint"/> + <field name="tile column number" size="12" start="0" type="uint"/> + </packet> + + <packet code="122" name="Multicore Rendering Supertile Configuration" cl="R"> + <field name="Supertile Raster Order" size="1" start="60" type="bool"/> + <field name="Multicore Enable" size="1" start="56" type="bool"/> + + <field name="Total Frame Height in Tiles" size="12" start="44" type="uint"/> + <field name="Total Frame Width in Tiles" size="12" start="32" type="uint"/> + + <field name="Total Frame Height in Supertiles" size="8" start="24" type="uint"/> + <field name="Total Frame Width in Supertiles" size="8" start="16" type="uint"/> + + <field name="Supertile Height in Tiles minus 1" size="8" start="8" type="uint"/> + <field name="Supertile Width in Tiles minus 1" size="8" start="0" type="uint"/> + </packet> + + <packet code="123" name="Multicore Rendering Tile List Set Base" cl="R"> + <field name="address" size="26" start="6" type="address"/> + <field name="Tile List Set Number" size="4" start="0" type="uint"/> + </packet> + + <!-- add fields --> + <packet code="125" name="Tile Coordinates Implicit"/> + + <packet code="126" name="Tile List Initial Block Size"> + <field name="Use auto-chained tile lists" size="1" start="2" type="bool"/> + + <field name="Size of first block in chained tile lists" size="2" start="0" type="uint"> + <value name="tile allocation block size 64b" value="0"/> + <value name="tile allocation block size 128b" value="1"/> + <value name="tile allocation block size 256b" value="2"/> + </field> + </packet> + + <struct name="GL Shader State Record"> + <field name="Point size in shaded vertex data" size="1" start="0" type="bool"/> + <field name="Enable clipping" size="1" start="1" type="bool"/> + <field name="Vertex ID read by coordinate shader" size="1" start="2" type="bool"/> + <field name="Instance ID read by coordinate shader" size="1" start="3" type="bool"/> + <field name="Vertex ID read by vertex shader" size="1" start="4" type="bool"/> + <field name="Instance ID read by vertex shader" size="1" start="5" type="bool"/> + <field name="Fragment shader does Z writes" size="1" start="6" type="bool"/> + <field name="Turn off early-z test" size="1" start="7" type="bool"/> + <field name="Coordinate shader has separate input and output VPM blocks" size="1" start="8" type="bool"/> + <field name="Vertex shader has separate input and output VPM blocks" size="1" start="9" type="bool"/> + <field name="Fragment shader uses real pixel centre W in addition to centroid W2" size="1" start="10" type="bool"/> + + <field name="Number of varyings in Fragment Shader" size="8" start="2b" type="uint"/> + <field name="Coordinate Shader output VPM segment size" size="8" start="4b" type="uint"/> + <field name="Coordinate Shader input VPM segment size" size="8" start="5b" type="uint"/> + <field name="Vertex Shader output VPM segment size" size="8" start="6b" type="uint"/> + <field name="Vertex Shader input VPM segment size" size="8" start="7b" type="uint"/> + <field name="Address of default attribute values" size="32" start="8b" type="address"/> + <field name="Fragment Shader Code Address" size="29" start="99" type="address"/> + <field name="2-way threadable" size="1" start="96" type="bool"/> + <field name="4-way threadable" size="1" start="97" type="bool"/> + <field name="Propagate NaNs" size="1" start="98" type="bool"/> + <field name="Fragment Shader Uniforms Address" size="32" start="16b" type="address"/> + <field name="Vertex Shader Code Address" size="32" start="20b" type="address"/> + <field name="Vertex Shader Uniforms Address" size="32" start="24b" type="address"/> + <field name="Coordinate Shader Code Address" size="32" start="28b" type="address"/> + <field name="Coordinate Shader Uniforms Address" size="32" start="32b" type="address"/> + </struct> + + <struct name="GL Shader State Attribute Record"> + <field name="Address" size="32" start="0" type="address"/> + + <field name="Vec size" size="2" start="32" type="uint"/> + <field name="Type" size="3" start="34" type="uint"> + <value name="Attribute half-float" value="1"/> + <value name="Attribute float" value="2"/> + <value name="Attribute fixed" value="3"/> + <value name="Attribute byte" value="4"/> + <value name="Attribute short" value="5"/> + <value name="Attribute int" value="6"/> + <value name="Attribute int2_10_10_10" value="7"/> + </field> + <field name="Signed int type" size="1" start="37" type="bool"/> + <field name="Normalized int type" size="1" start="38" type="bool"/> + <field name="Read as int/uint" size="1" start="39" type="bool"/> + + <field name="Number of values read by Coordinate shader" size="4" start="40" type="uint"/> + <field name="Number of values read by Vertex shader" size="4" start="44" type="uint"/> + + <field name="Instance Divisor" size="16" start="6b" type="uint"/> + <field name="Stride" size="32" start="8b" type="uint"/> + </struct> + + <struct name="VPM generic block write setup"> + <field name="id" size="2" start="30" type="uint" default="0"/> + <field name="id0" size="3" start="27" type="uint" default="0"/> + + <field name="horiz" size="1" start="24" type="bool"/> + <field name="laned" size="1" start="23" type="bool"/> + <field name="segs" size="1" start="22" type="bool"/> + <field name="stride" size="7" start="15" type="int"/> + + <field name="size" size="2" start="13" type="uint"> + <value name="VPM setup size 8-bit" value="0"/> + <value name="VPM setup size 16-bit" value="1"/> + <value name="VPM setup size 32-bit" value="2"/> + </field> + + <field name="addr" size="13" start="0" type="uint"/> + </struct> + + <struct name="VPM generic block read setup"> + <field name="id" size="2" start="30" type="uint" default="1"/> + + <field name="horiz" size="1" start="29" type="bool"/> + <field name="laned" size="1" start="28" type="bool"/> + <field name="segs" size="1" start="27" type="bool"/> + <field name="num" size="5" start="22" type="uint"/> + <field name="stride" size="7" start="15" type="int"/> + + <field name="size" size="2" start="13" type="uint"> + <value name="VPM setup size 8-bit" value="0"/> + <value name="VPM setup size 16-bit" value="1"/> + <value name="VPM setup size 32-bit" value="2"/> + </field> + + <field name="addr" size="13" start="0" type="uint"/> + </struct> + + <struct name="Texture Uniform Parameter 0 CFG_MODE=1"> + <field name="Per-pixel mask enable" size="1" start="31" type="bool"/> + + <field name="Texel offset for r coordinate" size="4" start="27" type="int"/> + <field name="Texel offset for t coordinate" size="4" start="23" type="int"/> + <field name="Texel offset for s coordinate" size="4" start="19" type="int"/> + + <field name="R Wrap Mode" size="3" start="16" type="uint"> + <value name="Wrap mode REPEAT" value="0"/> + <value name="Wrap mode CLAMP" value="1"/> + <value name="Wrap mode MIRROR" value="2"/> + <value name="Wrap mode BORDER" value="3"/> + <value name="Wrap mode MIRROR_ONCE" value="4"/> + </field> + + <field name="T Wrap Mode" size="3" start="13" type="uint"> + <value name="Wrap mode REPEAT" value="0"/> + <value name="Wrap mode CLAMP" value="1"/> + <value name="Wrap mode MIRROR" value="2"/> + <value name="Wrap mode BORDER" value="3"/> + <value name="Wrap mode MIRROR_ONCE" value="4"/> + </field> + + <field name="S Wrap Mode" size="3" start="10" type="uint"> + <value name="Wrap mode REPEAT" value="0"/> + <value name="Wrap mode CLAMP" value="1"/> + <value name="Wrap mode MIRROR" value="2"/> + <value name="Wrap mode BORDER" value="3"/> + <value name="Wrap mode MIRROR_ONCE" value="4"/> + </field> + + <field name="New configuration mode" size="1" start="9" type="bool" default="1"/> + + <field name="Shadow" size="1" start="8" type="bool"/> + <field name="Coefficient lookup mode" size="1" start="7" type="bool"/> + <field name="Disable AutoLOD, use bias only" size="1" start="6" type="bool"/> + <field name="Bias supplied" size="1" start="5" type="bool"/> + <field name="Gather sample mode" size="1" start="4" type="bool"/> + <field name="Fetch sample mode" size="1" start="3" type="bool"/> + + <field name="Lookup Type" size="3" start="0" type="bool"> + <value name="Texture 2D" value="0"/> + <value name="Texture 2D array" value="1"/> + <value name="Texture 3D" value="2"/> + <value name="Texture Cube Map" value="3"/> + <value name="Texture 1D" value="4"/> + <value name="Texture 1D Array" value="5"/> + <value name="Texture Child Image" value="6"/> + </field> + </struct> + + <struct name="Texture Uniform Parameter 1 CFG_MODE=1"> + <field name="Texture state record base address" size="32" start="0" type="address"/> + <field name="Return word 3 of texture data" size="1" start="3" type="bool"/> + <field name="Return word 2 of texture data" size="1" start="2" type="bool"/> + <field name="Return word 1 of texture data" size="1" start="1" type="bool"/> + <field name="Return word 0 of texture data" size="1" start="0" type="bool"/> + </struct> + + <struct name="Texture Shader State"> + <field name="Level 0 is strictly UIF" size="1" start="254" type="bool"/> + <field name="Level 0 XOR enable" size="1" start="252" type="bool"/> + <field name="Level 0 UB_PAD" size="4" start="248" type="uint"/> + + <field name="Base Level" size="4" start="240" type="uint"/> + <field name="Fixed Bias" size="16" start="224" type="s8.8"/> + <field name="Max Level-of-Detail" size="16" start="208" type="s8.8"/> + <field name="Min Level-of-Detail" size="16" start="192" type="s8.8"/> + + <field name="Border Color alpha" size="16" start="176" type="uint"/> + <field name="Border Color blue" size="16" start="160" type="uint"/> + <field name="Border Color green" size="16" start="144" type="uint"/> + <field name="Border Color red" size="16" start="128" type="uint"/> + + <field name="Flip S and T on incoming request" size="1" start="127" type="bool"/> + <field name="Flip ETC Y" size="1" start="126" type="bool" default="1"/> + <field name="Flip texture Y Axis" size="1" start="125" type="bool"/> + <field name="Flip texture X Axis" size="1" start="124" type="bool"/> + + <field name="Swizzle A" size="3" start="121" type="uint"> + <value name="Swizzle Zero" value="0"/> + <value name="Swizzle One" value="1"/> + <value name="Swizzle Red" value="2"/> + <value name="Swizzle Green" value="3"/> + <value name="Swizzle Blue" value="4"/> + <value name="Swizzle Alpha" value="5"/> + </field> + + <field name="Swizzle B" size="3" start="118" type="uint"/> + <field name="Swizzle G" size="3" start="115" type="uint"/> + <field name="Swizzle R" size="3" start="112" type="uint"/> + + <field name="Depth Compare Function" size="3" start="109" type="Compare Function"/> + + <field name="sRGB" size="1" start="107" type="bool"/> + + <field name="Texture type" size="7" start="100" type="uint"/> + + <field name="Image Depth" size="14" start="86" type="uint"/> + <field name="Image Height" size="14" start="72" type="uint"/> + <field name="Image Width" size="14" start="58" type="uint"/> + + <field name="Array Stride (64-byte aligned)" size="26" start="32" type="uint"/> + + <field name="Texture base pointer" size="32" start="0" type="address"/> + + <field name="Minification Filter" size="3" start="1" type="uint"/> + <field name="Magnification Filter" size="1" start="0" type="uint"/> + </struct> + + <enum name="Texture Data Formats"> + <value name="Texture Data Format R8" value="0"/> + <value name="Texture Data Format R8 SNORM" value="1"/> + <value name="Texture Data Format RG8" value="2"/> + <value name="Texture Data Format RG8 SNORM" value="3"/> + <value name="Texture Data Format RGBA8" value="4"/> + <value name="Texture Data Format RGBA8 SNORM" value="5"/> + <value name="Texture Data Format RGB565" value="6"/> + <value name="Texture Data Format RGBA4" value="7"/> + <value name="Texture Data Format RGB5_A1" value="8"/> + <value name="Texture Data Format RGB10_A2" value="9"/> + <value name="Texture Data Format R16" value="10"/> + <value name="Texture Data Format R16 SNORM" value="11"/> + <value name="Texture Data Format RG16" value="12"/> + <value name="Texture Data Format RG16 SNORM" value="13"/> + <value name="Texture Data Format RGBA16" value="14"/> + <value name="Texture Data Format RGBA16 SNORM" value="15"/> + <value name="Texture Data Format R16F" value="16"/> + <value name="Texture Data Format RG16F" value="17"/> + <value name="Texture Data Format RGBA16F" value="18"/> + <value name="Texture Data Format R11F_G11F_B10F" value="19"/> + <value name="Texture Data Format RGB9_E5" value="20"/> + <value name="Texture Data Format DEPTH COMP16" value="21"/> + <value name="Texture Data Format DEPTH COMP24" value="22"/> + <value name="Texture Data Format DEPTH COMP32F" value="23"/> + <value name="Texture Data Format DEPTH24_X8" value="24"/> + <value name="Texture Data Format R4" value="25"/> + <value name="Texture Data Format R1" value="26"/> + <!-- generic unfiltered 8-bit sample --> + <value name="Texture Data Format S8" value="27"/> + <!-- generic unfiltered 16-bit sample --> + <value name="Texture Data Format S16" value="28"/> + <!-- generic unfiltered 32-bit sample --> + <value name="Texture Data Format R32F" value="29"/> + <!-- generic unfiltered 64-bit sample --> + <value name="Texture Data Format RG32F" value="30"/> + <!-- generic unfiltered 128-bit sample --> + <value name="Texture Data Format RGBA32F" value="31"/> + + <value name="Texture Data Format RGB8_ETC2" value="32"/> + <value name="Texture Data Format RGB8_PUNCHTHROUGH_ALPHA1" value="33"/> + + <value name="Texture Data Format R11_EAC" value="34"/> + <value name="Texture Data Format SIGNED_R11_EAC" value="35"/> + <value name="Texture Data Format RG11_EAC" value="36"/> + <value name="Texture Data Format SIGNED_RG11_EAC" value="37"/> + + <value name="Texture Data Format RGBA8_ETC2_EAC" value="38"/> + <value name="Texture Data Format YCBCR_LUMA" value="39"/> + <value name="Texture Data Format YCBCR_420_CHROMA" value="40"/> + + <value name="Texture Data Format BC1" value="48"/> + <value name="Texture Data Format BC2" value="49"/> + <value name="Texture Data Format BC3" value="50"/> + + <value name="Texture Data Format ASTC_4x4" value="64"/> + <value name="Texture Data Format ASTC_5x4" value="65"/> + <value name="Texture Data Format ASTC_5x5" value="66"/> + <value name="Texture Data Format ASTC_6x5" value="67"/> + <value name="Texture Data Format ASTC_6x6" value="68"/> + <value name="Texture Data Format ASTC_8x5" value="69"/> + <value name="Texture Data Format ASTC_8x6" value="70"/> + <value name="Texture Data Format ASTC_8x8" value="71"/> + <value name="Texture Data Format ASTC_10x5" value="72"/> + <value name="Texture Data Format ASTC_10x6" value="73"/> + <value name="Texture Data Format ASTC_10x8" value="74"/> + <value name="Texture Data Format ASTC_10x10" value="75"/> + <value name="Texture Data Format ASTC_12x10" value="76"/> + <value name="Texture Data Format ASTC_12x12" value="77"/> + </enum> +</vcxml> diff --git a/lib/mesa/src/broadcom/cle/v3d_packet_v33_pack.h b/lib/mesa/src/broadcom/cle/v3d_packet_v33_pack.h new file mode 100644 index 000000000..934b0de4f --- /dev/null +++ b/lib/mesa/src/broadcom/cle/v3d_packet_v33_pack.h @@ -0,0 +1,3733 @@ +/* Generated code, see packets.xml and gen_packet_header.py */ + + +/* Packets, enums and structures for V3D 3.3. + * + * This file has been generated, do not hand edit. + */ + +#ifndef V3D33_PACK_H +#define V3D33_PACK_H + +#include "v3d_packet_helpers.h" + + +enum V3D33_Compare_Function { + V3D_COMPARE_FUNC_NEVER = 0, + V3D_COMPARE_FUNC_LESS = 1, + V3D_COMPARE_FUNC_EQUAL = 2, + V3D_COMPARE_FUNC_LEQUAL = 3, + V3D_COMPARE_FUNC_GREATER = 4, + V3D_COMPARE_FUNC_NOTEQUAL = 5, + V3D_COMPARE_FUNC_GEQUAL = 6, + V3D_COMPARE_FUNC_ALWAYS = 7, +}; + +enum V3D33_Blend_Factor { + V3D_BLEND_FACTOR_ZERO = 0, + V3D_BLEND_FACTOR_ONE = 1, + V3D_BLEND_FACTOR_SRC_COLOR = 2, + V3D_BLEND_FACTOR_INV_SRC_COLOR = 3, + V3D_BLEND_FACTOR_DST_COLOR = 4, + V3D_BLEND_FACTOR_INV_DST_COLOR = 5, + V3D_BLEND_FACTOR_SRC_ALPHA = 6, + V3D_BLEND_FACTOR_INV_SRC_ALPHA = 7, + V3D_BLEND_FACTOR_DST_ALPHA = 8, + V3D_BLEND_FACTOR_INV_DST_ALPHA = 9, + V3D_BLEND_FACTOR_CONST_COLOR = 10, + V3D_BLEND_FACTOR_INV_CONST_COLOR = 11, + V3D_BLEND_FACTOR_CONST_ALPHA = 12, + V3D_BLEND_FACTOR_INV_CONST_ALPHA = 13, + V3D_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14, +}; + +enum V3D33_Blend_Mode { + V3D_BLEND_MODE_ADD = 0, + V3D_BLEND_MODE_SUB = 1, + V3D_BLEND_MODE_RSUB = 2, + V3D_BLEND_MODE_MIN = 3, + V3D_BLEND_MODE_MAX = 4, + V3D_BLEND_MODE_MUL = 5, + V3D_BLEND_MODE_SCREEN = 6, + V3D_BLEND_MODE_DARKEN = 7, + V3D_BLEND_MODE_LIGHTEN = 8, +}; + +enum V3D33_Stencil_Op { + V3D_STENCIL_OP_ZERO = 0, + V3D_STENCIL_OP_KEEP = 1, + V3D_STENCIL_OP_REPLACE = 2, + V3D_STENCIL_OP_INCR = 3, + V3D_STENCIL_OP_DECR = 4, + V3D_STENCIL_OP_INVERT = 5, + V3D_STENCIL_OP_INCWRAP = 6, + V3D_STENCIL_OP_DECWRAP = 7, +}; + +enum V3D33_Primitive { + V3D_PRIM_POINTS = 0, + V3D_PRIM_LINES = 1, + V3D_PRIM_LINE_LOOP = 2, + V3D_PRIM_LINE_STRIP = 3, + V3D_PRIM_TRIANGLES = 4, + V3D_PRIM_TRIANGLE_STRIP = 5, + V3D_PRIM_TRIANGLE_FAN = 6, + V3D_PRIM_POINTS_TF = 16, + V3D_PRIM_LINES_TF = 17, + V3D_PRIM_LINE_LOOP_TF = 18, + V3D_PRIM_LINE_STRIP_TF = 19, + V3D_PRIM_TRIANGLES_TF = 20, + V3D_PRIM_TRIANGLE_STRIP_TF = 21, + V3D_PRIM_TRIANGLE_FAN_TF = 22, +}; + +#define V3D33_HALT_opcode 0 +#define V3D33_HALT_header \ + .opcode = 0 + +struct V3D33_HALT { + uint32_t opcode; +}; + +static inline void +V3D33_HALT_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_HALT * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_HALT_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_HALT_unpack(const uint8_t * restrict cl, + struct V3D33_HALT * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_NOP_opcode 1 +#define V3D33_NOP_header \ + .opcode = 1 + +struct V3D33_NOP { + uint32_t opcode; +}; + +static inline void +V3D33_NOP_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_NOP * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_NOP_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_NOP_unpack(const uint8_t * restrict cl, + struct V3D33_NOP * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_FLUSH_opcode 4 +#define V3D33_FLUSH_header \ + .opcode = 4 + +struct V3D33_FLUSH { + uint32_t opcode; +}; + +static inline void +V3D33_FLUSH_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_FLUSH * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_FLUSH_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_FLUSH_unpack(const uint8_t * restrict cl, + struct V3D33_FLUSH * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_FLUSH_ALL_STATE_opcode 5 +#define V3D33_FLUSH_ALL_STATE_header \ + .opcode = 5 + +struct V3D33_FLUSH_ALL_STATE { + uint32_t opcode; +}; + +static inline void +V3D33_FLUSH_ALL_STATE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_FLUSH_ALL_STATE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_FLUSH_ALL_STATE_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_FLUSH_ALL_STATE_unpack(const uint8_t * restrict cl, + struct V3D33_FLUSH_ALL_STATE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_START_TILE_BINNING_opcode 6 +#define V3D33_START_TILE_BINNING_header \ + .opcode = 6 + +struct V3D33_START_TILE_BINNING { + uint32_t opcode; +}; + +static inline void +V3D33_START_TILE_BINNING_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_START_TILE_BINNING * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_START_TILE_BINNING_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_START_TILE_BINNING_unpack(const uint8_t * restrict cl, + struct V3D33_START_TILE_BINNING * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_INCREMENT_SEMAPHORE_opcode 7 +#define V3D33_INCREMENT_SEMAPHORE_header \ + .opcode = 7 + +struct V3D33_INCREMENT_SEMAPHORE { + uint32_t opcode; +}; + +static inline void +V3D33_INCREMENT_SEMAPHORE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_INCREMENT_SEMAPHORE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_INCREMENT_SEMAPHORE_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_INCREMENT_SEMAPHORE_unpack(const uint8_t * restrict cl, + struct V3D33_INCREMENT_SEMAPHORE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_WAIT_ON_SEMAPHORE_opcode 8 +#define V3D33_WAIT_ON_SEMAPHORE_header \ + .opcode = 8 + +struct V3D33_WAIT_ON_SEMAPHORE { + uint32_t opcode; +}; + +static inline void +V3D33_WAIT_ON_SEMAPHORE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_WAIT_ON_SEMAPHORE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_WAIT_ON_SEMAPHORE_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_WAIT_ON_SEMAPHORE_unpack(const uint8_t * restrict cl, + struct V3D33_WAIT_ON_SEMAPHORE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_WAIT_FOR_PREVIOUS_FRAME_opcode 9 +#define V3D33_WAIT_FOR_PREVIOUS_FRAME_header \ + .opcode = 9 + +struct V3D33_WAIT_FOR_PREVIOUS_FRAME { + uint32_t opcode; +}; + +static inline void +V3D33_WAIT_FOR_PREVIOUS_FRAME_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_WAIT_FOR_PREVIOUS_FRAME * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_WAIT_FOR_PREVIOUS_FRAME_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_WAIT_FOR_PREVIOUS_FRAME_unpack(const uint8_t * restrict cl, + struct V3D33_WAIT_FOR_PREVIOUS_FRAME * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_ENABLE_Z_ONLY_RENDERING_opcode 10 +#define V3D33_ENABLE_Z_ONLY_RENDERING_header \ + .opcode = 10 + +struct V3D33_ENABLE_Z_ONLY_RENDERING { + uint32_t opcode; +}; + +static inline void +V3D33_ENABLE_Z_ONLY_RENDERING_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_ENABLE_Z_ONLY_RENDERING * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_ENABLE_Z_ONLY_RENDERING_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_ENABLE_Z_ONLY_RENDERING_unpack(const uint8_t * restrict cl, + struct V3D33_ENABLE_Z_ONLY_RENDERING * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_DISABLE_Z_ONLY_RENDERING_opcode 11 +#define V3D33_DISABLE_Z_ONLY_RENDERING_header \ + .opcode = 11 + +struct V3D33_DISABLE_Z_ONLY_RENDERING { + uint32_t opcode; +}; + +static inline void +V3D33_DISABLE_Z_ONLY_RENDERING_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_DISABLE_Z_ONLY_RENDERING * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_DISABLE_Z_ONLY_RENDERING_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_DISABLE_Z_ONLY_RENDERING_unpack(const uint8_t * restrict cl, + struct V3D33_DISABLE_Z_ONLY_RENDERING * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_END_OF_Z_ONLY_RENDERING_IN_FRAME_opcode 12 +#define V3D33_END_OF_Z_ONLY_RENDERING_IN_FRAME_header\ + .opcode = 12 + +struct V3D33_END_OF_Z_ONLY_RENDERING_IN_FRAME { + uint32_t opcode; +}; + +static inline void +V3D33_END_OF_Z_ONLY_RENDERING_IN_FRAME_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_END_OF_Z_ONLY_RENDERING_IN_FRAME * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_END_OF_Z_ONLY_RENDERING_IN_FRAME_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_END_OF_Z_ONLY_RENDERING_IN_FRAME_unpack(const uint8_t * restrict cl, + struct V3D33_END_OF_Z_ONLY_RENDERING_IN_FRAME * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_END_OF_RENDERING_opcode 13 +#define V3D33_END_OF_RENDERING_header \ + .opcode = 13 + +struct V3D33_END_OF_RENDERING { + uint32_t opcode; +}; + +static inline void +V3D33_END_OF_RENDERING_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_END_OF_RENDERING * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_END_OF_RENDERING_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_END_OF_RENDERING_unpack(const uint8_t * restrict cl, + struct V3D33_END_OF_RENDERING * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_WAIT_FOR_TRANSFORM_FEEDBACK_opcode 14 +#define V3D33_WAIT_FOR_TRANSFORM_FEEDBACK_header\ + .opcode = 14 + +struct V3D33_WAIT_FOR_TRANSFORM_FEEDBACK { + uint32_t opcode; + uint32_t block_count; +}; + +static inline void +V3D33_WAIT_FOR_TRANSFORM_FEEDBACK_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_WAIT_FOR_TRANSFORM_FEEDBACK * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->block_count, 0, 7); + +} + +#define V3D33_WAIT_FOR_TRANSFORM_FEEDBACK_length 2 +#ifdef __gen_unpack_address +static inline void +V3D33_WAIT_FOR_TRANSFORM_FEEDBACK_unpack(const uint8_t * restrict cl, + struct V3D33_WAIT_FOR_TRANSFORM_FEEDBACK * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->block_count = __gen_unpack_uint(cl, 8, 15); +} +#endif + + +#define V3D33_BRANCH_TO_AUTO_CHAINED_SUB_LIST_opcode 15 +#define V3D33_BRANCH_TO_AUTO_CHAINED_SUB_LIST_header\ + .opcode = 15 + +struct V3D33_BRANCH_TO_AUTO_CHAINED_SUB_LIST { + uint32_t opcode; + __gen_address_type address; +}; + +static inline void +V3D33_BRANCH_TO_AUTO_CHAINED_SUB_LIST_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_BRANCH_TO_AUTO_CHAINED_SUB_LIST * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + __gen_emit_reloc(data, &values->address); + cl[ 1] = __gen_address_offset(&values->address); + + cl[ 2] = __gen_address_offset(&values->address) >> 8; + + cl[ 3] = __gen_address_offset(&values->address) >> 16; + + cl[ 4] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_BRANCH_TO_AUTO_CHAINED_SUB_LIST_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_BRANCH_TO_AUTO_CHAINED_SUB_LIST_unpack(const uint8_t * restrict cl, + struct V3D33_BRANCH_TO_AUTO_CHAINED_SUB_LIST * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 8, 39); +} +#endif + + +#define V3D33_BRANCH_opcode 16 +#define V3D33_BRANCH_header \ + .opcode = 16 + +struct V3D33_BRANCH { + uint32_t opcode; + __gen_address_type address; +}; + +static inline void +V3D33_BRANCH_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_BRANCH * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + __gen_emit_reloc(data, &values->address); + cl[ 1] = __gen_address_offset(&values->address); + + cl[ 2] = __gen_address_offset(&values->address) >> 8; + + cl[ 3] = __gen_address_offset(&values->address) >> 16; + + cl[ 4] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_BRANCH_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_BRANCH_unpack(const uint8_t * restrict cl, + struct V3D33_BRANCH * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 8, 39); +} +#endif + + +#define V3D33_BRANCH_TO_SUB_LIST_opcode 17 +#define V3D33_BRANCH_TO_SUB_LIST_header \ + .opcode = 17 + +struct V3D33_BRANCH_TO_SUB_LIST { + uint32_t opcode; + __gen_address_type address; +}; + +static inline void +V3D33_BRANCH_TO_SUB_LIST_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_BRANCH_TO_SUB_LIST * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + __gen_emit_reloc(data, &values->address); + cl[ 1] = __gen_address_offset(&values->address); + + cl[ 2] = __gen_address_offset(&values->address) >> 8; + + cl[ 3] = __gen_address_offset(&values->address) >> 16; + + cl[ 4] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_BRANCH_TO_SUB_LIST_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_BRANCH_TO_SUB_LIST_unpack(const uint8_t * restrict cl, + struct V3D33_BRANCH_TO_SUB_LIST * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 8, 39); +} +#endif + + +#define V3D33_RETURN_FROM_SUB_LIST_opcode 18 +#define V3D33_RETURN_FROM_SUB_LIST_header \ + .opcode = 18 + +struct V3D33_RETURN_FROM_SUB_LIST { + uint32_t opcode; +}; + +static inline void +V3D33_RETURN_FROM_SUB_LIST_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_RETURN_FROM_SUB_LIST * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_RETURN_FROM_SUB_LIST_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_RETURN_FROM_SUB_LIST_unpack(const uint8_t * restrict cl, + struct V3D33_RETURN_FROM_SUB_LIST * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_FLUSH_VCD_CACHE_opcode 19 +#define V3D33_FLUSH_VCD_CACHE_header \ + .opcode = 19 + +struct V3D33_FLUSH_VCD_CACHE { + uint32_t opcode; +}; + +static inline void +V3D33_FLUSH_VCD_CACHE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_FLUSH_VCD_CACHE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_FLUSH_VCD_CACHE_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_FLUSH_VCD_CACHE_unpack(const uint8_t * restrict cl, + struct V3D33_FLUSH_VCD_CACHE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST_opcode 20 +#define V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST_header\ + .opcode = 20 + +struct V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST { + uint32_t opcode; + __gen_address_type start; + __gen_address_type end; +}; + +static inline void +V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + __gen_emit_reloc(data, &values->start); + cl[ 1] = __gen_address_offset(&values->start); + + cl[ 2] = __gen_address_offset(&values->start) >> 8; + + cl[ 3] = __gen_address_offset(&values->start) >> 16; + + cl[ 4] = __gen_address_offset(&values->start) >> 24; + + __gen_emit_reloc(data, &values->end); + cl[ 5] = __gen_address_offset(&values->end); + + cl[ 6] = __gen_address_offset(&values->end) >> 8; + + cl[ 7] = __gen_address_offset(&values->end) >> 16; + + cl[ 8] = __gen_address_offset(&values->end) >> 24; + +} + +#define V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST_unpack(const uint8_t * restrict cl, + struct V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->start = __gen_unpack_address(cl, 8, 39); + values->end = __gen_unpack_address(cl, 40, 71); +} +#endif + + +#define V3D33_BRANCH_TO_IMPLICIT_TILE_LIST_opcode 21 +#define V3D33_BRANCH_TO_IMPLICIT_TILE_LIST_header\ + .opcode = 21 + +struct V3D33_BRANCH_TO_IMPLICIT_TILE_LIST { + uint32_t opcode; + uint32_t tile_list_set_number; +}; + +static inline void +V3D33_BRANCH_TO_IMPLICIT_TILE_LIST_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_BRANCH_TO_IMPLICIT_TILE_LIST * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->tile_list_set_number, 0, 7); + +} + +#define V3D33_BRANCH_TO_IMPLICIT_TILE_LIST_length 2 +#ifdef __gen_unpack_address +static inline void +V3D33_BRANCH_TO_IMPLICIT_TILE_LIST_unpack(const uint8_t * restrict cl, + struct V3D33_BRANCH_TO_IMPLICIT_TILE_LIST * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->tile_list_set_number = __gen_unpack_uint(cl, 8, 15); +} +#endif + + +#define V3D33_BRANCH_TO_EXPLICIT_SUPERTILE_opcode 22 +#define V3D33_BRANCH_TO_EXPLICIT_SUPERTILE_header\ + .opcode = 22 + +struct V3D33_BRANCH_TO_EXPLICIT_SUPERTILE { + uint32_t opcode; + __gen_address_type absolute_address_of_explicit_supertile_render_list; + uint32_t explicit_supertile_number; + uint32_t row_number; + uint32_t column_number; +}; + +static inline void +V3D33_BRANCH_TO_EXPLICIT_SUPERTILE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_BRANCH_TO_EXPLICIT_SUPERTILE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->column_number, 0, 7); + + cl[ 2] = __gen_uint(values->row_number, 0, 7); + + cl[ 3] = __gen_uint(values->explicit_supertile_number, 0, 7); + + __gen_emit_reloc(data, &values->absolute_address_of_explicit_supertile_render_list); + cl[ 4] = __gen_address_offset(&values->absolute_address_of_explicit_supertile_render_list); + + cl[ 5] = __gen_address_offset(&values->absolute_address_of_explicit_supertile_render_list) >> 8; + + cl[ 6] = __gen_address_offset(&values->absolute_address_of_explicit_supertile_render_list) >> 16; + + cl[ 7] = __gen_address_offset(&values->absolute_address_of_explicit_supertile_render_list) >> 24; + +} + +#define V3D33_BRANCH_TO_EXPLICIT_SUPERTILE_length 8 +#ifdef __gen_unpack_address +static inline void +V3D33_BRANCH_TO_EXPLICIT_SUPERTILE_unpack(const uint8_t * restrict cl, + struct V3D33_BRANCH_TO_EXPLICIT_SUPERTILE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->absolute_address_of_explicit_supertile_render_list = __gen_unpack_address(cl, 32, 63); + values->explicit_supertile_number = __gen_unpack_uint(cl, 24, 31); + values->row_number = __gen_unpack_uint(cl, 16, 23); + values->column_number = __gen_unpack_uint(cl, 8, 15); +} +#endif + + +#define V3D33_SUPERTILE_COORDINATES_opcode 23 +#define V3D33_SUPERTILE_COORDINATES_header \ + .opcode = 23 + +struct V3D33_SUPERTILE_COORDINATES { + uint32_t opcode; + uint32_t row_number_in_supertiles; + uint32_t column_number_in_supertiles; +}; + +static inline void +V3D33_SUPERTILE_COORDINATES_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_SUPERTILE_COORDINATES * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->column_number_in_supertiles, 0, 7); + + cl[ 2] = __gen_uint(values->row_number_in_supertiles, 0, 7); + +} + +#define V3D33_SUPERTILE_COORDINATES_length 3 +#ifdef __gen_unpack_address +static inline void +V3D33_SUPERTILE_COORDINATES_unpack(const uint8_t * restrict cl, + struct V3D33_SUPERTILE_COORDINATES * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->row_number_in_supertiles = __gen_unpack_uint(cl, 16, 23); + values->column_number_in_supertiles = __gen_unpack_uint(cl, 8, 15); +} +#endif + + +#define V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_opcode 24 +#define V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_header\ + .opcode = 24 + +struct V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER { + uint32_t opcode; +}; + +static inline void +V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_unpack(const uint8_t * restrict cl, + struct V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_opcode 25 +#define V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_header\ + .opcode = 25 + +struct V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED { + uint32_t opcode; + uint32_t disable_color_buffer_write; + bool enable_z_write; + bool enable_stencil_write; + bool disable_colour_buffers_clear_on_write; + bool disable_stencil_buffer_clear_on_write; + bool disable_z_buffer_clear_on_write; + bool disable_fast_opportunistic_write_out_in_multisample_mode; + bool last_tile_of_frame; +}; + +static inline void +V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->enable_z_write, 7, 7) | + __gen_uint(values->enable_stencil_write, 6, 6) | + __gen_uint(values->disable_colour_buffers_clear_on_write, 4, 4) | + __gen_uint(values->disable_stencil_buffer_clear_on_write, 3, 3) | + __gen_uint(values->disable_z_buffer_clear_on_write, 2, 2) | + __gen_uint(values->disable_fast_opportunistic_write_out_in_multisample_mode, 1, 1) | + __gen_uint(values->last_tile_of_frame, 0, 0); + + cl[ 2] = __gen_uint(values->disable_color_buffer_write, 0, 7); + +} + +#define V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_length 3 +#ifdef __gen_unpack_address +static inline void +V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_unpack(const uint8_t * restrict cl, + struct V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->disable_color_buffer_write = __gen_unpack_uint(cl, 16, 23); + values->enable_z_write = __gen_unpack_uint(cl, 15, 15); + values->enable_stencil_write = __gen_unpack_uint(cl, 14, 14); + values->disable_colour_buffers_clear_on_write = __gen_unpack_uint(cl, 12, 12); + values->disable_stencil_buffer_clear_on_write = __gen_unpack_uint(cl, 11, 11); + values->disable_z_buffer_clear_on_write = __gen_unpack_uint(cl, 10, 10); + values->disable_fast_opportunistic_write_out_in_multisample_mode = __gen_unpack_uint(cl, 9, 9); + values->last_tile_of_frame = __gen_unpack_uint(cl, 8, 8); +} +#endif + + +#define V3D33_RELOAD_TILE_COLOUR_BUFFER_opcode 26 +#define V3D33_RELOAD_TILE_COLOUR_BUFFER_header \ + .opcode = 26 + +struct V3D33_RELOAD_TILE_COLOUR_BUFFER { + uint32_t opcode; + uint32_t disable_colour_buffer_load; + bool enable_z_load; + bool enable_stencil_load; +}; + +static inline void +V3D33_RELOAD_TILE_COLOUR_BUFFER_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_RELOAD_TILE_COLOUR_BUFFER * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->enable_z_load, 7, 7) | + __gen_uint(values->enable_stencil_load, 6, 6); + + cl[ 2] = __gen_uint(values->disable_colour_buffer_load, 0, 7); + +} + +#define V3D33_RELOAD_TILE_COLOUR_BUFFER_length 3 +#ifdef __gen_unpack_address +static inline void +V3D33_RELOAD_TILE_COLOUR_BUFFER_unpack(const uint8_t * restrict cl, + struct V3D33_RELOAD_TILE_COLOUR_BUFFER * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->disable_colour_buffer_load = __gen_unpack_uint(cl, 16, 23); + values->enable_z_load = __gen_unpack_uint(cl, 15, 15); + values->enable_stencil_load = __gen_unpack_uint(cl, 14, 14); +} +#endif + + +#define V3D33_END_OF_TILE_MARKER_opcode 27 +#define V3D33_END_OF_TILE_MARKER_header \ + .opcode = 27 + +struct V3D33_END_OF_TILE_MARKER { + uint32_t opcode; +}; + +static inline void +V3D33_END_OF_TILE_MARKER_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_END_OF_TILE_MARKER * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_END_OF_TILE_MARKER_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_END_OF_TILE_MARKER_unpack(const uint8_t * restrict cl, + struct V3D33_END_OF_TILE_MARKER * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_STORE_TILE_BUFFER_GENERAL_opcode 29 +#define V3D33_STORE_TILE_BUFFER_GENERAL_header \ + .opcode = 29 + +struct V3D33_STORE_TILE_BUFFER_GENERAL { + uint32_t opcode; + __gen_address_type address; + uint32_t padded_height_of_output_image_in_uif_blocks; + bool xor_uif; + bool last_tile_of_frame; + bool disable_colour_buffers_clear_on_write; + bool disable_stencil_buffer_clear_on_write; + bool disable_z_buffer_clear_on_write; + bool raw_mode; + uint32_t buffer_to_store; +#define RENDER_TARGET_0 0 +#define RENDER_TARGET_1 1 +#define RENDER_TARGET_2 2 +#define RENDER_TARGET_3 3 +#define NONE 8 +#define Z 9 +#define STENCIL 10 +#define ZSTENCIL 11 +}; + +static inline void +V3D33_STORE_TILE_BUFFER_GENERAL_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_STORE_TILE_BUFFER_GENERAL * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->disable_colour_buffers_clear_on_write, 7, 7) | + __gen_uint(values->disable_stencil_buffer_clear_on_write, 6, 6) | + __gen_uint(values->disable_z_buffer_clear_on_write, 5, 5) | + __gen_uint(values->raw_mode, 4, 4) | + __gen_uint(values->buffer_to_store, 0, 3); + + cl[ 2] = __gen_uint(values->padded_height_of_output_image_in_uif_blocks, 3, 15) | + __gen_uint(values->xor_uif, 2, 2) | + __gen_uint(values->last_tile_of_frame, 0, 0); + + __gen_emit_reloc(data, &values->address); + cl[ 3] = __gen_address_offset(&values->address) | + __gen_uint(values->padded_height_of_output_image_in_uif_blocks, 3, 15) >> 8; + + cl[ 4] = __gen_address_offset(&values->address) >> 8; + + cl[ 5] = __gen_address_offset(&values->address) >> 16; + + cl[ 6] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_STORE_TILE_BUFFER_GENERAL_length 7 +#ifdef __gen_unpack_address +static inline void +V3D33_STORE_TILE_BUFFER_GENERAL_unpack(const uint8_t * restrict cl, + struct V3D33_STORE_TILE_BUFFER_GENERAL * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 24, 55); + values->padded_height_of_output_image_in_uif_blocks = __gen_unpack_uint(cl, 19, 31); + values->xor_uif = __gen_unpack_uint(cl, 18, 18); + values->last_tile_of_frame = __gen_unpack_uint(cl, 16, 16); + values->disable_colour_buffers_clear_on_write = __gen_unpack_uint(cl, 15, 15); + values->disable_stencil_buffer_clear_on_write = __gen_unpack_uint(cl, 14, 14); + values->disable_z_buffer_clear_on_write = __gen_unpack_uint(cl, 13, 13); + values->raw_mode = __gen_unpack_uint(cl, 12, 12); + values->buffer_to_store = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_LOAD_TILE_BUFFER_GENERAL_opcode 30 +#define V3D33_LOAD_TILE_BUFFER_GENERAL_header \ + .opcode = 30 + +struct V3D33_LOAD_TILE_BUFFER_GENERAL { + uint32_t opcode; + __gen_address_type address; + uint32_t padded_height_of_output_image_in_uif_blocks; + bool xor_uif; + bool raw_mode; + uint32_t buffer_to_load; +#define RENDER_TARGET_0 0 +#define RENDER_TARGET_1 1 +#define RENDER_TARGET_2 2 +#define RENDER_TARGET_3 3 +#define NONE 8 +#define Z 9 +#define STENCIL 10 +#define ZSTENCIL 11 +}; + +static inline void +V3D33_LOAD_TILE_BUFFER_GENERAL_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_LOAD_TILE_BUFFER_GENERAL * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->raw_mode, 4, 4) | + __gen_uint(values->buffer_to_load, 0, 3); + + cl[ 2] = __gen_uint(values->padded_height_of_output_image_in_uif_blocks, 3, 15) | + __gen_uint(values->xor_uif, 2, 2); + + cl[ 3] = __gen_uint(values->padded_height_of_output_image_in_uif_blocks, 3, 15) >> 8; + + __gen_emit_reloc(data, &values->address); + cl[ 4] = __gen_address_offset(&values->address); + + cl[ 5] = __gen_address_offset(&values->address) >> 8; + + cl[ 6] = __gen_address_offset(&values->address) >> 16; + +} + +#define V3D33_LOAD_TILE_BUFFER_GENERAL_length 7 +#ifdef __gen_unpack_address +static inline void +V3D33_LOAD_TILE_BUFFER_GENERAL_unpack(const uint8_t * restrict cl, + struct V3D33_LOAD_TILE_BUFFER_GENERAL * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 32, 55); + values->padded_height_of_output_image_in_uif_blocks = __gen_unpack_uint(cl, 19, 31); + values->xor_uif = __gen_unpack_uint(cl, 18, 18); + values->raw_mode = __gen_unpack_uint(cl, 12, 12); + values->buffer_to_load = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_INDEXED_PRIMITIVE_LIST_opcode 32 +#define V3D33_INDEXED_PRIMITIVE_LIST_header \ + .opcode = 32 + +struct V3D33_INDEXED_PRIMITIVE_LIST { + uint32_t opcode; + uint32_t minimum_index; + bool enable_primitive_restarts; + uint32_t maximum_index; + __gen_address_type address_of_indices_list; + uint32_t length; + uint32_t index_type; +#define INDEX_TYPE_8_BIT 0 +#define INDEX_TYPE_16_BIT 1 +#define INDEX_TYPE_32_BIT 2 + uint32_t mode; +}; + +static inline void +V3D33_INDEXED_PRIMITIVE_LIST_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_INDEXED_PRIMITIVE_LIST * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->index_type, 6, 7) | + __gen_uint(values->mode, 0, 4); + + + memcpy(&cl[2], &values->length, sizeof(values->length)); + __gen_emit_reloc(data, &values->address_of_indices_list); + cl[ 6] = __gen_address_offset(&values->address_of_indices_list); + + cl[ 7] = __gen_address_offset(&values->address_of_indices_list) >> 8; + + cl[ 8] = __gen_address_offset(&values->address_of_indices_list) >> 16; + + cl[ 9] = __gen_address_offset(&values->address_of_indices_list) >> 24; + + cl[10] = __gen_uint(values->maximum_index, 0, 30); + + cl[11] = __gen_uint(values->maximum_index, 0, 30) >> 8; + + cl[12] = __gen_uint(values->maximum_index, 0, 30) >> 16; + + cl[13] = __gen_uint(values->enable_primitive_restarts, 7, 7) | + __gen_uint(values->maximum_index, 0, 30) >> 24; + + + memcpy(&cl[14], &values->minimum_index, sizeof(values->minimum_index)); +} + +#define V3D33_INDEXED_PRIMITIVE_LIST_length 18 +#ifdef __gen_unpack_address +static inline void +V3D33_INDEXED_PRIMITIVE_LIST_unpack(const uint8_t * restrict cl, + struct V3D33_INDEXED_PRIMITIVE_LIST * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->minimum_index = __gen_unpack_uint(cl, 112, 143); + values->enable_primitive_restarts = __gen_unpack_uint(cl, 111, 111); + values->maximum_index = __gen_unpack_uint(cl, 80, 110); + values->address_of_indices_list = __gen_unpack_address(cl, 48, 79); + values->length = __gen_unpack_uint(cl, 16, 47); + values->index_type = __gen_unpack_uint(cl, 14, 15); + values->mode = __gen_unpack_uint(cl, 8, 12); +} +#endif + + +#define V3D33_INDEXED_INSTANCED_PRIMITIVE_LIST_opcode 34 +#define V3D33_INDEXED_INSTANCED_PRIMITIVE_LIST_header\ + .opcode = 34 + +struct V3D33_INDEXED_INSTANCED_PRIMITIVE_LIST { + uint32_t opcode; + bool enable_primitive_restarts; + uint32_t maximum_index; + __gen_address_type address_of_indices_list; + uint32_t number_of_instances; + uint32_t instance_length; + uint32_t index_type; +#define INDEX_TYPE_8_BIT 0 +#define INDEX_TYPE_16_BIT 1 +#define INDEX_TYPE_32_BIT 2 + enum V3D33_Primitive mode; +}; + +static inline void +V3D33_INDEXED_INSTANCED_PRIMITIVE_LIST_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_INDEXED_INSTANCED_PRIMITIVE_LIST * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->index_type, 6, 7) | + __gen_uint(values->mode, 0, 4); + + + memcpy(&cl[2], &values->instance_length, sizeof(values->instance_length)); + + memcpy(&cl[6], &values->number_of_instances, sizeof(values->number_of_instances)); + __gen_emit_reloc(data, &values->address_of_indices_list); + cl[10] = __gen_address_offset(&values->address_of_indices_list); + + cl[11] = __gen_address_offset(&values->address_of_indices_list) >> 8; + + cl[12] = __gen_address_offset(&values->address_of_indices_list) >> 16; + + cl[13] = __gen_address_offset(&values->address_of_indices_list) >> 24; + + cl[14] = __gen_uint(values->maximum_index, 0, 30); + + cl[15] = __gen_uint(values->maximum_index, 0, 30) >> 8; + + cl[16] = __gen_uint(values->maximum_index, 0, 30) >> 16; + + cl[17] = __gen_uint(values->enable_primitive_restarts, 7, 7) | + __gen_uint(values->maximum_index, 0, 30) >> 24; + +} + +#define V3D33_INDEXED_INSTANCED_PRIMITIVE_LIST_length 18 +#ifdef __gen_unpack_address +static inline void +V3D33_INDEXED_INSTANCED_PRIMITIVE_LIST_unpack(const uint8_t * restrict cl, + struct V3D33_INDEXED_INSTANCED_PRIMITIVE_LIST * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->enable_primitive_restarts = __gen_unpack_uint(cl, 143, 143); + values->maximum_index = __gen_unpack_uint(cl, 112, 142); + values->address_of_indices_list = __gen_unpack_address(cl, 80, 111); + values->number_of_instances = __gen_unpack_uint(cl, 48, 79); + values->instance_length = __gen_unpack_uint(cl, 16, 47); + values->index_type = __gen_unpack_uint(cl, 14, 15); + values->mode = __gen_unpack_uint(cl, 8, 12); +} +#endif + + +#define V3D33_VERTEX_ARRAY_PRIMITIVES_opcode 36 +#define V3D33_VERTEX_ARRAY_PRIMITIVES_header \ + .opcode = 36 + +struct V3D33_VERTEX_ARRAY_PRIMITIVES { + uint32_t opcode; + uint32_t index_of_first_vertex; + uint32_t length; + enum V3D33_Primitive mode; +}; + +static inline void +V3D33_VERTEX_ARRAY_PRIMITIVES_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_VERTEX_ARRAY_PRIMITIVES * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->mode, 0, 7); + + + memcpy(&cl[2], &values->length, sizeof(values->length)); + + memcpy(&cl[6], &values->index_of_first_vertex, sizeof(values->index_of_first_vertex)); +} + +#define V3D33_VERTEX_ARRAY_PRIMITIVES_length 10 +#ifdef __gen_unpack_address +static inline void +V3D33_VERTEX_ARRAY_PRIMITIVES_unpack(const uint8_t * restrict cl, + struct V3D33_VERTEX_ARRAY_PRIMITIVES * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->index_of_first_vertex = __gen_unpack_uint(cl, 48, 79); + values->length = __gen_unpack_uint(cl, 16, 47); + values->mode = __gen_unpack_uint(cl, 8, 15); +} +#endif + + +#define V3D33_VERTEX_ARRAY_INSTANCED_PRIMITIVES_opcode 38 +#define V3D33_VERTEX_ARRAY_INSTANCED_PRIMITIVES_header\ + .opcode = 38 + +struct V3D33_VERTEX_ARRAY_INSTANCED_PRIMITIVES { + uint32_t opcode; + uint32_t index_of_first_vertex; + uint32_t number_of_instances; + uint32_t instance_length; + enum V3D33_Primitive mode; +}; + +static inline void +V3D33_VERTEX_ARRAY_INSTANCED_PRIMITIVES_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_VERTEX_ARRAY_INSTANCED_PRIMITIVES * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->mode, 0, 7); + + + memcpy(&cl[2], &values->instance_length, sizeof(values->instance_length)); + + memcpy(&cl[6], &values->number_of_instances, sizeof(values->number_of_instances)); + + memcpy(&cl[10], &values->index_of_first_vertex, sizeof(values->index_of_first_vertex)); +} + +#define V3D33_VERTEX_ARRAY_INSTANCED_PRIMITIVES_length 14 +#ifdef __gen_unpack_address +static inline void +V3D33_VERTEX_ARRAY_INSTANCED_PRIMITIVES_unpack(const uint8_t * restrict cl, + struct V3D33_VERTEX_ARRAY_INSTANCED_PRIMITIVES * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->index_of_first_vertex = __gen_unpack_uint(cl, 80, 111); + values->number_of_instances = __gen_unpack_uint(cl, 48, 79); + values->instance_length = __gen_unpack_uint(cl, 16, 47); + values->mode = __gen_unpack_uint(cl, 8, 15); +} +#endif + + +#define V3D33_BASE_VERTEX_BASE_INSTANCE_opcode 43 +#define V3D33_BASE_VERTEX_BASE_INSTANCE_header \ + .opcode = 43 + +struct V3D33_BASE_VERTEX_BASE_INSTANCE { + uint32_t opcode; + uint32_t base_instance; + uint32_t base_vertex; +}; + +static inline void +V3D33_BASE_VERTEX_BASE_INSTANCE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_BASE_VERTEX_BASE_INSTANCE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + + memcpy(&cl[1], &values->base_vertex, sizeof(values->base_vertex)); + + memcpy(&cl[5], &values->base_instance, sizeof(values->base_instance)); +} + +#define V3D33_BASE_VERTEX_BASE_INSTANCE_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_BASE_VERTEX_BASE_INSTANCE_unpack(const uint8_t * restrict cl, + struct V3D33_BASE_VERTEX_BASE_INSTANCE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->base_instance = __gen_unpack_uint(cl, 40, 71); + values->base_vertex = __gen_unpack_uint(cl, 8, 39); +} +#endif + + +#define V3D33_PRIMITIVE_LIST_FORMAT_opcode 56 +#define V3D33_PRIMITIVE_LIST_FORMAT_header \ + .opcode = 56 + +struct V3D33_PRIMITIVE_LIST_FORMAT { + uint32_t opcode; + uint32_t data_type; +#define LIST_INDEXED 0 +#define LIST_32_BIT_X_Y 1 + uint32_t primitive_type; +#define LIST_POINTS 0 +#define LIST_LINES 1 +#define LIST_TRIANGLES 2 +}; + +static inline void +V3D33_PRIMITIVE_LIST_FORMAT_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_PRIMITIVE_LIST_FORMAT * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->data_type, 6, 6) | + __gen_uint(values->primitive_type, 0, 5); + +} + +#define V3D33_PRIMITIVE_LIST_FORMAT_length 2 +#ifdef __gen_unpack_address +static inline void +V3D33_PRIMITIVE_LIST_FORMAT_unpack(const uint8_t * restrict cl, + struct V3D33_PRIMITIVE_LIST_FORMAT * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->data_type = __gen_unpack_uint(cl, 14, 14); + values->primitive_type = __gen_unpack_uint(cl, 8, 13); +} +#endif + + +#define V3D33_GL_SHADER_STATE_opcode 64 +#define V3D33_GL_SHADER_STATE_header \ + .opcode = 64 + +struct V3D33_GL_SHADER_STATE { + uint32_t opcode; + __gen_address_type address; + uint32_t number_of_attribute_arrays; +}; + +static inline void +V3D33_GL_SHADER_STATE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_GL_SHADER_STATE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + __gen_emit_reloc(data, &values->address); + cl[ 1] = __gen_address_offset(&values->address) | + __gen_uint(values->number_of_attribute_arrays, 0, 4); + + cl[ 2] = __gen_address_offset(&values->address) >> 8; + + cl[ 3] = __gen_address_offset(&values->address) >> 16; + + cl[ 4] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_GL_SHADER_STATE_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_GL_SHADER_STATE_unpack(const uint8_t * restrict cl, + struct V3D33_GL_SHADER_STATE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 13, 39); + values->number_of_attribute_arrays = __gen_unpack_uint(cl, 8, 12); +} +#endif + + +#define V3D33_TRANSFORM_FEEDBACK_ENABLE_opcode 74 +#define V3D33_TRANSFORM_FEEDBACK_ENABLE_header \ + .opcode = 74 + +struct V3D33_TRANSFORM_FEEDBACK_ENABLE { + uint32_t opcode; + uint32_t number_of_32_bit_output_buffer_address_following; + uint32_t number_of_16_bit_output_data_specs_following; +}; + +static inline void +V3D33_TRANSFORM_FEEDBACK_ENABLE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TRANSFORM_FEEDBACK_ENABLE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = 0; + cl[ 2] = __gen_uint(values->number_of_32_bit_output_buffer_address_following, 0, 2) | + __gen_uint(values->number_of_16_bit_output_data_specs_following, 3, 7); + +} + +#define V3D33_TRANSFORM_FEEDBACK_ENABLE_length 3 +#ifdef __gen_unpack_address +static inline void +V3D33_TRANSFORM_FEEDBACK_ENABLE_unpack(const uint8_t * restrict cl, + struct V3D33_TRANSFORM_FEEDBACK_ENABLE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->number_of_32_bit_output_buffer_address_following = __gen_unpack_uint(cl, 16, 18); + values->number_of_16_bit_output_data_specs_following = __gen_unpack_uint(cl, 19, 23); +} +#endif + + +#define V3D33_FLUSH_TRANSFORM_FEEDBACK_DATA_opcode 75 +#define V3D33_FLUSH_TRANSFORM_FEEDBACK_DATA_header\ + .opcode = 75 + +struct V3D33_FLUSH_TRANSFORM_FEEDBACK_DATA { + uint32_t opcode; +}; + +static inline void +V3D33_FLUSH_TRANSFORM_FEEDBACK_DATA_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_FLUSH_TRANSFORM_FEEDBACK_DATA * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_FLUSH_TRANSFORM_FEEDBACK_DATA_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_FLUSH_TRANSFORM_FEEDBACK_DATA_unpack(const uint8_t * restrict cl, + struct V3D33_FLUSH_TRANSFORM_FEEDBACK_DATA * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC_header\ + + +struct V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC { + uint32_t first_shaded_vertex_value_to_output; + uint32_t number_of_consecutive_vertex_values_to_output_as_32_bit_values_minus_1; + uint32_t output_buffer_to_write_to; +}; + +static inline void +V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC * restrict values) +{ + cl[ 0] = __gen_uint(values->first_shaded_vertex_value_to_output, 0, 7); + + cl[ 1] = __gen_uint(values->number_of_consecutive_vertex_values_to_output_as_32_bit_values_minus_1, 0, 3) | + __gen_uint(values->output_buffer_to_write_to, 4, 5); + +} + +#define V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC_length 2 +#ifdef __gen_unpack_address +static inline void +V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC_unpack(const uint8_t * restrict cl, + struct V3D33_TRANSFORM_FEEDBACK_OUTPUT_DATA_SPEC * restrict values) +{ + values->first_shaded_vertex_value_to_output = __gen_unpack_uint(cl, 0, 7); + values->number_of_consecutive_vertex_values_to_output_as_32_bit_values_minus_1 = __gen_unpack_uint(cl, 8, 11); + values->output_buffer_to_write_to = __gen_unpack_uint(cl, 12, 13); +} +#endif + + +#define V3D33_TRANSFORM_FEEDBACK_OUTPUT_ADDRESS_header\ + + +struct V3D33_TRANSFORM_FEEDBACK_OUTPUT_ADDRESS { + __gen_address_type address; +}; + +static inline void +V3D33_TRANSFORM_FEEDBACK_OUTPUT_ADDRESS_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TRANSFORM_FEEDBACK_OUTPUT_ADDRESS * restrict values) +{ + __gen_emit_reloc(data, &values->address); + cl[ 0] = __gen_address_offset(&values->address); + + cl[ 1] = __gen_address_offset(&values->address) >> 8; + + cl[ 2] = __gen_address_offset(&values->address) >> 16; + + cl[ 3] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_TRANSFORM_FEEDBACK_OUTPUT_ADDRESS_length 4 +#ifdef __gen_unpack_address +static inline void +V3D33_TRANSFORM_FEEDBACK_OUTPUT_ADDRESS_unpack(const uint8_t * restrict cl, + struct V3D33_TRANSFORM_FEEDBACK_OUTPUT_ADDRESS * restrict values) +{ + values->address = __gen_unpack_address(cl, 0, 31); +} +#endif + + +#define V3D33_STENCIL_CONFIG_opcode 80 +#define V3D33_STENCIL_CONFIG_header \ + .opcode = 80 + +struct V3D33_STENCIL_CONFIG { + uint32_t opcode; + uint32_t stencil_write_mask; + bool back_config; + bool front_config; + enum V3D33_Stencil_Op stencil_pass_op; + enum V3D33_Stencil_Op depth_test_fail_op; + enum V3D33_Stencil_Op stencil_test_fail_op; + enum V3D33_Compare_Function stencil_test_function; + uint32_t stencil_test_mask; + uint32_t stencil_ref_value; +}; + +static inline void +V3D33_STENCIL_CONFIG_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_STENCIL_CONFIG * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->stencil_ref_value, 0, 7); + + cl[ 2] = __gen_uint(values->stencil_test_mask, 0, 7); + + cl[ 3] = __gen_uint(values->depth_test_fail_op, 6, 8) | + __gen_uint(values->stencil_test_fail_op, 3, 5) | + __gen_uint(values->stencil_test_function, 0, 2); + + cl[ 4] = __gen_uint(values->back_config, 5, 5) | + __gen_uint(values->front_config, 4, 4) | + __gen_uint(values->stencil_pass_op, 1, 3) | + __gen_uint(values->depth_test_fail_op, 6, 8) >> 8; + + cl[ 5] = __gen_uint(values->stencil_write_mask, 0, 7); + +} + +#define V3D33_STENCIL_CONFIG_length 6 +#ifdef __gen_unpack_address +static inline void +V3D33_STENCIL_CONFIG_unpack(const uint8_t * restrict cl, + struct V3D33_STENCIL_CONFIG * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->stencil_write_mask = __gen_unpack_uint(cl, 40, 47); + values->back_config = __gen_unpack_uint(cl, 37, 37); + values->front_config = __gen_unpack_uint(cl, 36, 36); + values->stencil_pass_op = __gen_unpack_uint(cl, 33, 35); + values->depth_test_fail_op = __gen_unpack_uint(cl, 30, 32); + values->stencil_test_fail_op = __gen_unpack_uint(cl, 27, 29); + values->stencil_test_function = __gen_unpack_uint(cl, 24, 26); + values->stencil_test_mask = __gen_unpack_uint(cl, 16, 23); + values->stencil_ref_value = __gen_unpack_uint(cl, 8, 15); +} +#endif + + +#define V3D33_BLEND_CONFIG_opcode 84 +#define V3D33_BLEND_CONFIG_header \ + .opcode = 84 + +struct V3D33_BLEND_CONFIG { + uint32_t opcode; + uint32_t vg_coverage_modes; + enum V3D33_Blend_Factor colour_blend_dst_factor; + enum V3D33_Blend_Factor colour_blend_src_factor; + enum V3D33_Blend_Mode colour_blend_mode; + enum V3D33_Blend_Factor alpha_blend_dst_factor; + enum V3D33_Blend_Factor alpha_blend_src_factor; + enum V3D33_Blend_Mode alpha_blend_mode; +}; + +static inline void +V3D33_BLEND_CONFIG_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_BLEND_CONFIG * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->alpha_blend_src_factor, 4, 7) | + __gen_uint(values->alpha_blend_mode, 0, 3); + + cl[ 2] = __gen_uint(values->colour_blend_mode, 4, 7) | + __gen_uint(values->alpha_blend_dst_factor, 0, 3); + + cl[ 3] = __gen_uint(values->colour_blend_dst_factor, 4, 7) | + __gen_uint(values->colour_blend_src_factor, 0, 3); + + cl[ 4] = __gen_uint(values->vg_coverage_modes, 4, 5); + +} + +#define V3D33_BLEND_CONFIG_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_BLEND_CONFIG_unpack(const uint8_t * restrict cl, + struct V3D33_BLEND_CONFIG * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->vg_coverage_modes = __gen_unpack_uint(cl, 36, 37); + values->colour_blend_dst_factor = __gen_unpack_uint(cl, 28, 31); + values->colour_blend_src_factor = __gen_unpack_uint(cl, 24, 27); + values->colour_blend_mode = __gen_unpack_uint(cl, 20, 23); + values->alpha_blend_dst_factor = __gen_unpack_uint(cl, 16, 19); + values->alpha_blend_src_factor = __gen_unpack_uint(cl, 12, 15); + values->alpha_blend_mode = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_BLEND_CONSTANT_COLOUR_opcode 86 +#define V3D33_BLEND_CONSTANT_COLOUR_header \ + .opcode = 86 + +struct V3D33_BLEND_CONSTANT_COLOUR { + uint32_t opcode; + uint32_t alpha_f16; + uint32_t blue_f16; + uint32_t green_f16; + uint32_t red_f16; +}; + +static inline void +V3D33_BLEND_CONSTANT_COLOUR_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_BLEND_CONSTANT_COLOUR * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->red_f16, 0, 15); + + cl[ 2] = __gen_uint(values->red_f16, 0, 15) >> 8; + + cl[ 3] = __gen_uint(values->green_f16, 0, 15); + + cl[ 4] = __gen_uint(values->green_f16, 0, 15) >> 8; + + cl[ 5] = __gen_uint(values->blue_f16, 0, 15); + + cl[ 6] = __gen_uint(values->blue_f16, 0, 15) >> 8; + + cl[ 7] = __gen_uint(values->alpha_f16, 0, 15); + + cl[ 8] = __gen_uint(values->alpha_f16, 0, 15) >> 8; + +} + +#define V3D33_BLEND_CONSTANT_COLOUR_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_BLEND_CONSTANT_COLOUR_unpack(const uint8_t * restrict cl, + struct V3D33_BLEND_CONSTANT_COLOUR * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->alpha_f16 = __gen_unpack_uint(cl, 56, 71); + values->blue_f16 = __gen_unpack_uint(cl, 40, 55); + values->green_f16 = __gen_unpack_uint(cl, 24, 39); + values->red_f16 = __gen_unpack_uint(cl, 8, 23); +} +#endif + + +#define V3D33_COLOUR_WRITE_MASKS_opcode 87 +#define V3D33_COLOUR_WRITE_MASKS_header \ + .opcode = 87 + +struct V3D33_COLOUR_WRITE_MASKS { + uint32_t opcode; + uint32_t reserved; + uint32_t render_target_3_per_colour_component_write_masks; + uint32_t render_target_2_per_colour_component_write_masks; + uint32_t render_target_1_per_colour_component_write_masks; + uint32_t render_target_0_per_colour_component_write_masks; +}; + +static inline void +V3D33_COLOUR_WRITE_MASKS_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_COLOUR_WRITE_MASKS * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->render_target_1_per_colour_component_write_masks, 4, 7) | + __gen_uint(values->render_target_0_per_colour_component_write_masks, 0, 3); + + cl[ 2] = __gen_uint(values->render_target_3_per_colour_component_write_masks, 4, 7) | + __gen_uint(values->render_target_2_per_colour_component_write_masks, 0, 3); + + cl[ 3] = __gen_uint(values->reserved, 0, 15); + + cl[ 4] = __gen_uint(values->reserved, 0, 15) >> 8; + +} + +#define V3D33_COLOUR_WRITE_MASKS_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_COLOUR_WRITE_MASKS_unpack(const uint8_t * restrict cl, + struct V3D33_COLOUR_WRITE_MASKS * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->reserved = __gen_unpack_uint(cl, 24, 39); + values->render_target_3_per_colour_component_write_masks = __gen_unpack_uint(cl, 20, 23); + values->render_target_2_per_colour_component_write_masks = __gen_unpack_uint(cl, 16, 19); + values->render_target_1_per_colour_component_write_masks = __gen_unpack_uint(cl, 12, 15); + values->render_target_0_per_colour_component_write_masks = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_CONFIGURATION_BITS_opcode 96 +#define V3D33_CONFIGURATION_BITS_header \ + .opcode = 96 + +struct V3D33_CONFIGURATION_BITS { + uint32_t opcode; + bool direct3d_provoking_vertex; + bool direct3d_point_fill_mode; + bool blend_enable; + bool stencil_enable; + bool early_z_updates_enable; + bool early_z_enable; + bool z_updates_enable; + enum V3D33_Compare_Function depth_test_function; + bool direct3d_wireframe_triangles_mode; + uint32_t coverage_update_mode; + bool coverage_pipe_select; + uint32_t rasterizer_oversample_mode; + uint32_t line_rasterization; + bool enable_depth_offset; + bool clockwise_primitives; + bool enable_reverse_facing_primitive; + bool enable_forward_facing_primitive; +}; + +static inline void +V3D33_CONFIGURATION_BITS_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_CONFIGURATION_BITS * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->rasterizer_oversample_mode, 6, 7) | + __gen_uint(values->line_rasterization, 4, 5) | + __gen_uint(values->enable_depth_offset, 3, 3) | + __gen_uint(values->clockwise_primitives, 2, 2) | + __gen_uint(values->enable_reverse_facing_primitive, 1, 1) | + __gen_uint(values->enable_forward_facing_primitive, 0, 0); + + cl[ 2] = __gen_uint(values->z_updates_enable, 7, 7) | + __gen_uint(values->depth_test_function, 4, 6) | + __gen_uint(values->direct3d_wireframe_triangles_mode, 3, 3) | + __gen_uint(values->coverage_update_mode, 1, 2) | + __gen_uint(values->coverage_pipe_select, 0, 0); + + cl[ 3] = __gen_uint(values->direct3d_provoking_vertex, 5, 5) | + __gen_uint(values->direct3d_point_fill_mode, 4, 4) | + __gen_uint(values->blend_enable, 3, 3) | + __gen_uint(values->stencil_enable, 2, 2) | + __gen_uint(values->early_z_updates_enable, 1, 1) | + __gen_uint(values->early_z_enable, 0, 0); + +} + +#define V3D33_CONFIGURATION_BITS_length 4 +#ifdef __gen_unpack_address +static inline void +V3D33_CONFIGURATION_BITS_unpack(const uint8_t * restrict cl, + struct V3D33_CONFIGURATION_BITS * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->direct3d_provoking_vertex = __gen_unpack_uint(cl, 29, 29); + values->direct3d_point_fill_mode = __gen_unpack_uint(cl, 28, 28); + values->blend_enable = __gen_unpack_uint(cl, 27, 27); + values->stencil_enable = __gen_unpack_uint(cl, 26, 26); + values->early_z_updates_enable = __gen_unpack_uint(cl, 25, 25); + values->early_z_enable = __gen_unpack_uint(cl, 24, 24); + values->z_updates_enable = __gen_unpack_uint(cl, 23, 23); + values->depth_test_function = __gen_unpack_uint(cl, 20, 22); + values->direct3d_wireframe_triangles_mode = __gen_unpack_uint(cl, 19, 19); + values->coverage_update_mode = __gen_unpack_uint(cl, 17, 18); + values->coverage_pipe_select = __gen_unpack_uint(cl, 16, 16); + values->rasterizer_oversample_mode = __gen_unpack_uint(cl, 14, 15); + values->line_rasterization = __gen_unpack_uint(cl, 12, 13); + values->enable_depth_offset = __gen_unpack_uint(cl, 11, 11); + values->clockwise_primitives = __gen_unpack_uint(cl, 10, 10); + values->enable_reverse_facing_primitive = __gen_unpack_uint(cl, 9, 9); + values->enable_forward_facing_primitive = __gen_unpack_uint(cl, 8, 8); +} +#endif + + +#define V3D33_ZERO_ALL_FLAT_SHADE_FLAGS_opcode 97 +#define V3D33_ZERO_ALL_FLAT_SHADE_FLAGS_header \ + .opcode = 97 + +struct V3D33_ZERO_ALL_FLAT_SHADE_FLAGS { + uint32_t opcode; +}; + +static inline void +V3D33_ZERO_ALL_FLAT_SHADE_FLAGS_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_ZERO_ALL_FLAT_SHADE_FLAGS * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_ZERO_ALL_FLAT_SHADE_FLAGS_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_ZERO_ALL_FLAT_SHADE_FLAGS_unpack(const uint8_t * restrict cl, + struct V3D33_ZERO_ALL_FLAT_SHADE_FLAGS * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_FLAT_SHADE_FLAGS_opcode 98 +#define V3D33_FLAT_SHADE_FLAGS_header \ + .opcode = 98 + +struct V3D33_FLAT_SHADE_FLAGS { + uint32_t opcode; + uint32_t flat_shade_flags_for_varyings_v024; + uint32_t action_for_flat_shade_flags_of_higher_numbered_varyings; + uint32_t action_for_flat_shade_flags_of_lower_numbered_varyings; + uint32_t varying_offset_v0; +}; + +static inline void +V3D33_FLAT_SHADE_FLAGS_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_FLAT_SHADE_FLAGS * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->action_for_flat_shade_flags_of_higher_numbered_varyings, 6, 7) | + __gen_uint(values->action_for_flat_shade_flags_of_lower_numbered_varyings, 4, 5) | + __gen_uint(values->varying_offset_v0, 0, 3); + + cl[ 2] = __gen_uint(values->flat_shade_flags_for_varyings_v024, 0, 23); + + cl[ 3] = __gen_uint(values->flat_shade_flags_for_varyings_v024, 0, 23) >> 8; + + cl[ 4] = __gen_uint(values->flat_shade_flags_for_varyings_v024, 0, 23) >> 16; + +} + +#define V3D33_FLAT_SHADE_FLAGS_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_FLAT_SHADE_FLAGS_unpack(const uint8_t * restrict cl, + struct V3D33_FLAT_SHADE_FLAGS * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->flat_shade_flags_for_varyings_v024 = __gen_unpack_uint(cl, 16, 39); + values->action_for_flat_shade_flags_of_higher_numbered_varyings = __gen_unpack_uint(cl, 14, 15); + values->action_for_flat_shade_flags_of_lower_numbered_varyings = __gen_unpack_uint(cl, 12, 13); + values->varying_offset_v0 = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_POINT_SIZE_opcode 104 +#define V3D33_POINT_SIZE_header \ + .opcode = 104 + +struct V3D33_POINT_SIZE { + uint32_t opcode; + float point_size; +}; + +static inline void +V3D33_POINT_SIZE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_POINT_SIZE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + + memcpy(&cl[1], &values->point_size, sizeof(values->point_size)); +} + +#define V3D33_POINT_SIZE_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_POINT_SIZE_unpack(const uint8_t * restrict cl, + struct V3D33_POINT_SIZE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->point_size = __gen_unpack_float(cl, 8, 39); +} +#endif + + +#define V3D33_LINE_WIDTH_opcode 105 +#define V3D33_LINE_WIDTH_header \ + .opcode = 105 + +struct V3D33_LINE_WIDTH { + uint32_t opcode; + float line_width; +}; + +static inline void +V3D33_LINE_WIDTH_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_LINE_WIDTH * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + + memcpy(&cl[1], &values->line_width, sizeof(values->line_width)); +} + +#define V3D33_LINE_WIDTH_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_LINE_WIDTH_unpack(const uint8_t * restrict cl, + struct V3D33_LINE_WIDTH * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->line_width = __gen_unpack_float(cl, 8, 39); +} +#endif + + +#define V3D33_DEPTH_OFFSET_opcode 106 +#define V3D33_DEPTH_OFFSET_header \ + .opcode = 106 + +struct V3D33_DEPTH_OFFSET { + uint32_t opcode; + uint32_t depth_offset_units; + uint32_t depth_offset_factor; +}; + +static inline void +V3D33_DEPTH_OFFSET_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_DEPTH_OFFSET * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->depth_offset_factor, 0, 15); + + cl[ 2] = __gen_uint(values->depth_offset_factor, 0, 15) >> 8; + + cl[ 3] = __gen_uint(values->depth_offset_units, 0, 15); + + cl[ 4] = __gen_uint(values->depth_offset_units, 0, 15) >> 8; + +} + +#define V3D33_DEPTH_OFFSET_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_DEPTH_OFFSET_unpack(const uint8_t * restrict cl, + struct V3D33_DEPTH_OFFSET * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->depth_offset_units = __gen_unpack_uint(cl, 24, 39); + values->depth_offset_factor = __gen_unpack_uint(cl, 8, 23); +} +#endif + + +#define V3D33_CLIP_WINDOW_opcode 107 +#define V3D33_CLIP_WINDOW_header \ + .opcode = 107 + +struct V3D33_CLIP_WINDOW { + uint32_t opcode; + uint32_t clip_window_height_in_pixels; + uint32_t clip_window_width_in_pixels; + uint32_t clip_window_bottom_pixel_coordinate; + uint32_t clip_window_left_pixel_coordinate; +}; + +static inline void +V3D33_CLIP_WINDOW_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_CLIP_WINDOW * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->clip_window_left_pixel_coordinate, 0, 15); + + cl[ 2] = __gen_uint(values->clip_window_left_pixel_coordinate, 0, 15) >> 8; + + cl[ 3] = __gen_uint(values->clip_window_bottom_pixel_coordinate, 0, 15); + + cl[ 4] = __gen_uint(values->clip_window_bottom_pixel_coordinate, 0, 15) >> 8; + + cl[ 5] = __gen_uint(values->clip_window_width_in_pixels, 0, 15); + + cl[ 6] = __gen_uint(values->clip_window_width_in_pixels, 0, 15) >> 8; + + cl[ 7] = __gen_uint(values->clip_window_height_in_pixels, 0, 15); + + cl[ 8] = __gen_uint(values->clip_window_height_in_pixels, 0, 15) >> 8; + +} + +#define V3D33_CLIP_WINDOW_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_CLIP_WINDOW_unpack(const uint8_t * restrict cl, + struct V3D33_CLIP_WINDOW * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->clip_window_height_in_pixels = __gen_unpack_uint(cl, 56, 71); + values->clip_window_width_in_pixels = __gen_unpack_uint(cl, 40, 55); + values->clip_window_bottom_pixel_coordinate = __gen_unpack_uint(cl, 24, 39); + values->clip_window_left_pixel_coordinate = __gen_unpack_uint(cl, 8, 23); +} +#endif + + +#define V3D33_VIEWPORT_OFFSET_opcode 108 +#define V3D33_VIEWPORT_OFFSET_header \ + .opcode = 108 + +struct V3D33_VIEWPORT_OFFSET { + uint32_t opcode; + float viewport_centre_y_coordinate; + float viewport_centre_x_coordinate; +}; + +static inline void +V3D33_VIEWPORT_OFFSET_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_VIEWPORT_OFFSET * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_sfixed(values->viewport_centre_x_coordinate, 0, 31, 8); + + cl[ 2] = __gen_sfixed(values->viewport_centre_x_coordinate, 0, 31, 8) >> 8; + + cl[ 3] = __gen_sfixed(values->viewport_centre_x_coordinate, 0, 31, 8) >> 16; + + cl[ 4] = __gen_sfixed(values->viewport_centre_x_coordinate, 0, 31, 8) >> 24; + + cl[ 5] = __gen_sfixed(values->viewport_centre_y_coordinate, 0, 31, 8); + + cl[ 6] = __gen_sfixed(values->viewport_centre_y_coordinate, 0, 31, 8) >> 8; + + cl[ 7] = __gen_sfixed(values->viewport_centre_y_coordinate, 0, 31, 8) >> 16; + + cl[ 8] = __gen_sfixed(values->viewport_centre_y_coordinate, 0, 31, 8) >> 24; + +} + +#define V3D33_VIEWPORT_OFFSET_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_VIEWPORT_OFFSET_unpack(const uint8_t * restrict cl, + struct V3D33_VIEWPORT_OFFSET * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->viewport_centre_y_coordinate = __gen_unpack_sfixed(cl, 40, 71, 8); + values->viewport_centre_x_coordinate = __gen_unpack_sfixed(cl, 8, 39, 8); +} +#endif + + +#define V3D33_CLIPPER_Z_MIN_MAX_CLIPPING_PLANES_opcode 109 +#define V3D33_CLIPPER_Z_MIN_MAX_CLIPPING_PLANES_header\ + .opcode = 109 + +struct V3D33_CLIPPER_Z_MIN_MAX_CLIPPING_PLANES { + uint32_t opcode; + float maximum_zw; + float minimum_zw; +}; + +static inline void +V3D33_CLIPPER_Z_MIN_MAX_CLIPPING_PLANES_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_CLIPPER_Z_MIN_MAX_CLIPPING_PLANES * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + + memcpy(&cl[1], &values->minimum_zw, sizeof(values->minimum_zw)); + + memcpy(&cl[5], &values->maximum_zw, sizeof(values->maximum_zw)); +} + +#define V3D33_CLIPPER_Z_MIN_MAX_CLIPPING_PLANES_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_CLIPPER_Z_MIN_MAX_CLIPPING_PLANES_unpack(const uint8_t * restrict cl, + struct V3D33_CLIPPER_Z_MIN_MAX_CLIPPING_PLANES * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->maximum_zw = __gen_unpack_float(cl, 40, 71); + values->minimum_zw = __gen_unpack_float(cl, 8, 39); +} +#endif + + +#define V3D33_CLIPPER_XY_SCALING_opcode 110 +#define V3D33_CLIPPER_XY_SCALING_header \ + .opcode = 110 + +struct V3D33_CLIPPER_XY_SCALING { + uint32_t opcode; + float viewport_half_height_in_1_256th_of_pixel; + float viewport_half_width_in_1_256th_of_pixel; +}; + +static inline void +V3D33_CLIPPER_XY_SCALING_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_CLIPPER_XY_SCALING * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + + memcpy(&cl[1], &values->viewport_half_width_in_1_256th_of_pixel, sizeof(values->viewport_half_width_in_1_256th_of_pixel)); + + memcpy(&cl[5], &values->viewport_half_height_in_1_256th_of_pixel, sizeof(values->viewport_half_height_in_1_256th_of_pixel)); +} + +#define V3D33_CLIPPER_XY_SCALING_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_CLIPPER_XY_SCALING_unpack(const uint8_t * restrict cl, + struct V3D33_CLIPPER_XY_SCALING * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->viewport_half_height_in_1_256th_of_pixel = __gen_unpack_float(cl, 40, 71); + values->viewport_half_width_in_1_256th_of_pixel = __gen_unpack_float(cl, 8, 39); +} +#endif + + +#define V3D33_CLIPPER_Z_SCALE_AND_OFFSET_opcode 111 +#define V3D33_CLIPPER_Z_SCALE_AND_OFFSET_header \ + .opcode = 111 + +struct V3D33_CLIPPER_Z_SCALE_AND_OFFSET { + uint32_t opcode; + float viewport_z_offset_zc_to_zs; + float viewport_z_scale_zc_to_zs; +}; + +static inline void +V3D33_CLIPPER_Z_SCALE_AND_OFFSET_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_CLIPPER_Z_SCALE_AND_OFFSET * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + + memcpy(&cl[1], &values->viewport_z_scale_zc_to_zs, sizeof(values->viewport_z_scale_zc_to_zs)); + + memcpy(&cl[5], &values->viewport_z_offset_zc_to_zs, sizeof(values->viewport_z_offset_zc_to_zs)); +} + +#define V3D33_CLIPPER_Z_SCALE_AND_OFFSET_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_CLIPPER_Z_SCALE_AND_OFFSET_unpack(const uint8_t * restrict cl, + struct V3D33_CLIPPER_Z_SCALE_AND_OFFSET * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->viewport_z_offset_zc_to_zs = __gen_unpack_float(cl, 40, 71); + values->viewport_z_scale_zc_to_zs = __gen_unpack_float(cl, 8, 39); +} +#endif + + +#define V3D33_TILE_BINNING_MODE_CONFIGURATION_PART1_opcode 120 +#define V3D33_TILE_BINNING_MODE_CONFIGURATION_PART1_header\ + .opcode = 120, \ + .auto_initialize_tile_state_data_array = 1, \ + .sub_id = 0 + +struct V3D33_TILE_BINNING_MODE_CONFIGURATION_PART1 { + uint32_t opcode; + bool double_buffer_in_non_ms_mode; + bool multisample_mode_4x; + uint32_t maximum_bpp_of_all_render_targets; +#define RENDER_TARGET_MAXIMUM_32BPP 0 +#define RENDER_TARGET_MAXIMUM_64BPP 1 +#define RENDER_TARGET_MAXIMUM_128BPP 2 + uint32_t number_of_render_targets; + uint32_t height_in_tiles; + uint32_t width_in_tiles; + __gen_address_type tile_state_data_array_base_address; + uint32_t tile_allocation_block_size; +#define TILE_ALLOCATION_BLOCK_SIZE_64B 0 +#define TILE_ALLOCATION_BLOCK_SIZE_128B 1 +#define TILE_ALLOCATION_BLOCK_SIZE_256B 2 + uint32_t tile_allocation_initial_block_size; +#define TILE_ALLOCATION_INITIAL_BLOCK_SIZE_64B 0 +#define TILE_ALLOCATION_INITIAL_BLOCK_SIZE_128B 1 +#define TILE_ALLOCATION_INITIAL_BLOCK_SIZE_256B 2 + bool auto_initialize_tile_state_data_array; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_BINNING_MODE_CONFIGURATION_PART1_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_BINNING_MODE_CONFIGURATION_PART1 * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + __gen_emit_reloc(data, &values->tile_state_data_array_base_address); + cl[ 1] = __gen_address_offset(&values->tile_state_data_array_base_address) | + __gen_uint(values->tile_allocation_block_size, 4, 5) | + __gen_uint(values->tile_allocation_initial_block_size, 2, 3) | + __gen_uint(values->auto_initialize_tile_state_data_array, 1, 1) | + __gen_uint(values->sub_id, 0, 0); + + cl[ 2] = __gen_address_offset(&values->tile_state_data_array_base_address) >> 8; + + cl[ 3] = __gen_address_offset(&values->tile_state_data_array_base_address) >> 16; + + cl[ 4] = __gen_address_offset(&values->tile_state_data_array_base_address) >> 24; + + cl[ 5] = __gen_uint(values->width_in_tiles, 0, 11); + + cl[ 6] = __gen_uint(values->height_in_tiles, 4, 15) | + __gen_uint(values->width_in_tiles, 0, 11) >> 8; + + cl[ 7] = __gen_uint(values->height_in_tiles, 4, 15) >> 8; + + cl[ 8] = __gen_uint(values->double_buffer_in_non_ms_mode, 7, 7) | + __gen_uint(values->multisample_mode_4x, 6, 6) | + __gen_uint(values->maximum_bpp_of_all_render_targets, 4, 5) | + __gen_uint(values->number_of_render_targets, 0, 3); + +} + +#define V3D33_TILE_BINNING_MODE_CONFIGURATION_PART1_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_BINNING_MODE_CONFIGURATION_PART1_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_BINNING_MODE_CONFIGURATION_PART1 * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->double_buffer_in_non_ms_mode = __gen_unpack_uint(cl, 71, 71); + values->multisample_mode_4x = __gen_unpack_uint(cl, 70, 70); + values->maximum_bpp_of_all_render_targets = __gen_unpack_uint(cl, 68, 69); + values->number_of_render_targets = __gen_unpack_uint(cl, 64, 67); + values->height_in_tiles = __gen_unpack_uint(cl, 52, 63); + values->width_in_tiles = __gen_unpack_uint(cl, 40, 51); + values->tile_state_data_array_base_address = __gen_unpack_address(cl, 8, 39); + values->tile_allocation_block_size = __gen_unpack_uint(cl, 12, 13); + values->tile_allocation_initial_block_size = __gen_unpack_uint(cl, 10, 11); + values->auto_initialize_tile_state_data_array = __gen_unpack_uint(cl, 9, 9); + values->sub_id = __gen_unpack_uint(cl, 8, 8); +} +#endif + + +#define V3D33_TILE_BINNING_MODE_CONFIGURATION_PART2_opcode 120 +#define V3D33_TILE_BINNING_MODE_CONFIGURATION_PART2_header\ + .opcode = 120, \ + .sub_id = 1 + +struct V3D33_TILE_BINNING_MODE_CONFIGURATION_PART2 { + uint32_t opcode; + __gen_address_type tile_allocation_memory_address; + uint32_t tile_allocation_memory_size; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_BINNING_MODE_CONFIGURATION_PART2_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_BINNING_MODE_CONFIGURATION_PART2 * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->tile_allocation_memory_size, 0, 31) | + __gen_uint(values->sub_id, 0, 0); + + cl[ 2] = __gen_uint(values->tile_allocation_memory_size, 0, 31) >> 8; + + cl[ 3] = __gen_uint(values->tile_allocation_memory_size, 0, 31) >> 16; + + cl[ 4] = __gen_uint(values->tile_allocation_memory_size, 0, 31) >> 24; + + __gen_emit_reloc(data, &values->tile_allocation_memory_address); + cl[ 5] = __gen_address_offset(&values->tile_allocation_memory_address); + + cl[ 6] = __gen_address_offset(&values->tile_allocation_memory_address) >> 8; + + cl[ 7] = __gen_address_offset(&values->tile_allocation_memory_address) >> 16; + + cl[ 8] = __gen_address_offset(&values->tile_allocation_memory_address) >> 24; + +} + +#define V3D33_TILE_BINNING_MODE_CONFIGURATION_PART2_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_BINNING_MODE_CONFIGURATION_PART2_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_BINNING_MODE_CONFIGURATION_PART2 * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->tile_allocation_memory_address = __gen_unpack_address(cl, 40, 71); + values->tile_allocation_memory_size = __gen_unpack_uint(cl, 8, 39); + values->sub_id = __gen_unpack_uint(cl, 8, 8); +} +#endif + + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION_opcode 121 +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION_header\ + .opcode = 121, \ + .sub_id = 0 + +struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION { + uint32_t opcode; + uint32_t disable_render_target_stores; + bool enable_z_store; + bool enable_stencil_store; + bool early_z_disable; + uint32_t early_z_test_and_update_direction; +#define EARLY_Z_DIRECTION_LT_LE 0 +#define EARLY_Z_DIRECTION_GT_GE 1 + bool select_coverage_mode; + bool double_buffer_in_non_ms_mode; + bool multisample_mode_4x; + uint32_t maximum_bpp_of_all_render_targets; +#define RENDER_TARGET_MAXIMUM_32BPP 0 +#define RENDER_TARGET_MAXIMUM_64BPP 1 +#define RENDER_TARGET_MAXIMUM_128BPP 2 + uint32_t image_height_pixels; + uint32_t image_width_pixels; + uint32_t number_of_render_targets_minus_1; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->number_of_render_targets_minus_1, 4, 7) | + __gen_uint(values->sub_id, 0, 3); + + cl[ 2] = __gen_uint(values->image_width_pixels, 0, 15); + + cl[ 3] = __gen_uint(values->image_width_pixels, 0, 15) >> 8; + + cl[ 4] = __gen_uint(values->image_height_pixels, 0, 15); + + cl[ 5] = __gen_uint(values->image_height_pixels, 0, 15) >> 8; + + cl[ 6] = __gen_uint(values->early_z_disable, 6, 6) | + __gen_uint(values->early_z_test_and_update_direction, 5, 5) | + __gen_uint(values->select_coverage_mode, 4, 4) | + __gen_uint(values->double_buffer_in_non_ms_mode, 3, 3) | + __gen_uint(values->multisample_mode_4x, 2, 2) | + __gen_uint(values->maximum_bpp_of_all_render_targets, 0, 1); + + cl[ 7] = __gen_uint(values->enable_z_store, 7, 7) | + __gen_uint(values->enable_stencil_store, 6, 6); + + cl[ 8] = __gen_uint(values->disable_render_target_stores, 0, 7); + +} + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_COMMON_CONFIGURATION * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->disable_render_target_stores = __gen_unpack_uint(cl, 64, 71); + values->enable_z_store = __gen_unpack_uint(cl, 63, 63); + values->enable_stencil_store = __gen_unpack_uint(cl, 62, 62); + values->early_z_disable = __gen_unpack_uint(cl, 54, 54); + values->early_z_test_and_update_direction = __gen_unpack_uint(cl, 53, 53); + values->select_coverage_mode = __gen_unpack_uint(cl, 52, 52); + values->double_buffer_in_non_ms_mode = __gen_unpack_uint(cl, 51, 51); + values->multisample_mode_4x = __gen_unpack_uint(cl, 50, 50); + values->maximum_bpp_of_all_render_targets = __gen_unpack_uint(cl, 48, 49); + values->image_height_pixels = __gen_unpack_uint(cl, 32, 47); + values->image_width_pixels = __gen_unpack_uint(cl, 16, 31); + values->number_of_render_targets_minus_1 = __gen_unpack_uint(cl, 12, 15); + values->sub_id = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG_opcode 121 +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG_header\ + .opcode = 121, \ + .sub_id = 2 + +struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG { + uint32_t opcode; + __gen_address_type address; + uint32_t pad; + bool flip_y; + uint32_t memory_format; +#define MEMORY_FORMAT_RASTER 0 +#define MEMORY_FORMAT_LINEARTILE 1 +#define MEMORY_FORMAT_UB_LINEAR_1_UIF_BLOCK_WIDE 2 +#define MEMORY_FORMAT_UB_LINEAR_2_UIF_BLOCKS_WIDE 3 +#define MEMORY_FORMAT_UIF_NO_XOR 4 +#define MEMORY_FORMAT_UIF_XOR 5 + bool a_dithered; + bool bgr_dithered; + uint32_t output_image_format; +#define OUTPUT_IMAGE_FORMAT_SRGB8_ALPHA8 0 +#define OUTPUT_IMAGE_FORMAT_SRGB 1 +#define OUTPUT_IMAGE_FORMAT_RGB10_A2UI 2 +#define OUTPUT_IMAGE_FORMAT_RGB10_A2 3 +#define OUTPUT_IMAGE_FORMAT_ABGR1555 4 +#define OUTPUT_IMAGE_FORMAT_ALPHA_MASKED_ABGR1555 5 +#define OUTPUT_IMAGE_FORMAT_ABGR4444 6 +#define OUTPUT_IMAGE_FORMAT_BGR565 7 +#define OUTPUT_IMAGE_FORMAT_R11F_G11F_B10F 8 +#define OUTPUT_IMAGE_FORMAT_RGBA32F 9 +#define OUTPUT_IMAGE_FORMAT_RG32F 10 +#define OUTPUT_IMAGE_FORMAT_R32F 11 +#define OUTPUT_IMAGE_FORMAT_RGBA32I 12 +#define OUTPUT_IMAGE_FORMAT_RG32I 13 +#define OUTPUT_IMAGE_FORMAT_R32I 14 +#define OUTPUT_IMAGE_FORMAT_RGBA32UI 15 +#define OUTPUT_IMAGE_FORMAT_RG32UI 16 +#define OUTPUT_IMAGE_FORMAT_R32UI 17 +#define OUTPUT_IMAGE_FORMAT_RGBA16F 18 +#define OUTPUT_IMAGE_FORMAT_RG16F 19 +#define OUTPUT_IMAGE_FORMAT_R16F 20 +#define OUTPUT_IMAGE_FORMAT_RGBA16I 21 +#define OUTPUT_IMAGE_FORMAT_RG16I 22 +#define OUTPUT_IMAGE_FORMAT_R16I 23 +#define OUTPUT_IMAGE_FORMAT_RGBA16UI 24 +#define OUTPUT_IMAGE_FORMAT_RG16UI 25 +#define OUTPUT_IMAGE_FORMAT_R16UI 26 +#define OUTPUT_IMAGE_FORMAT_RGBA8 27 +#define OUTPUT_IMAGE_FORMAT_RGB8 28 +#define OUTPUT_IMAGE_FORMAT_RG8 29 +#define OUTPUT_IMAGE_FORMAT_R8 30 +#define OUTPUT_IMAGE_FORMAT_RGBA8I 31 +#define OUTPUT_IMAGE_FORMAT_RG8I 32 +#define OUTPUT_IMAGE_FORMAT_R8I 33 +#define OUTPUT_IMAGE_FORMAT_RGBA8UI 34 +#define OUTPUT_IMAGE_FORMAT_RG8UI 35 +#define OUTPUT_IMAGE_FORMAT_R8UI 36 +#define OUTPUT_IMAGE_FORMAT_SRGBX8 37 +#define OUTPUT_IMAGE_FORMAT_RGBX8 38 + uint32_t decimate_mode; + uint32_t internal_type; +#define INTERNAL_TYPE_8I 0 +#define INTERNAL_TYPE_8UI 1 +#define INTERNAL_TYPE_8 2 +#define INTERNAL_TYPE_16I 4 +#define INTERNAL_TYPE_16UI 5 +#define INTERNAL_TYPE_16F 6 +#define INTERNAL_TYPE_32I 8 +#define INTERNAL_TYPE_32UI 9 +#define INTERNAL_TYPE_32F 10 + uint32_t internal_bpp; +#define INTERNAL_BPP_32 0 +#define INTERNAL_BPP_64 1 +#define INTERNAL_BPP_128 2 + uint32_t render_target_number; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->render_target_number, 4, 7) | + __gen_uint(values->sub_id, 0, 3); + + cl[ 2] = __gen_uint(values->decimate_mode, 6, 7) | + __gen_uint(values->internal_type, 2, 5) | + __gen_uint(values->internal_bpp, 0, 1); + + cl[ 3] = __gen_uint(values->a_dithered, 7, 7) | + __gen_uint(values->bgr_dithered, 6, 6) | + __gen_uint(values->output_image_format, 0, 5); + + cl[ 4] = __gen_uint(values->pad, 4, 7) | + __gen_uint(values->flip_y, 3, 3) | + __gen_uint(values->memory_format, 0, 2); + + __gen_emit_reloc(data, &values->address); + cl[ 5] = __gen_address_offset(&values->address); + + cl[ 6] = __gen_address_offset(&values->address) >> 8; + + cl[ 7] = __gen_address_offset(&values->address) >> 16; + + cl[ 8] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_RENDER_TARGET_CONFIG * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 40, 71); + values->pad = __gen_unpack_uint(cl, 36, 39); + values->flip_y = __gen_unpack_uint(cl, 35, 35); + values->memory_format = __gen_unpack_uint(cl, 32, 34); + values->a_dithered = __gen_unpack_uint(cl, 31, 31); + values->bgr_dithered = __gen_unpack_uint(cl, 30, 30); + values->output_image_format = __gen_unpack_uint(cl, 24, 29); + values->decimate_mode = __gen_unpack_uint(cl, 22, 23); + values->internal_type = __gen_unpack_uint(cl, 18, 21); + values->internal_bpp = __gen_unpack_uint(cl, 16, 17); + values->render_target_number = __gen_unpack_uint(cl, 12, 15); + values->sub_id = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG_opcode 121 +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG_header\ + .opcode = 121, \ + .z_stencil_id = 0, \ + .sub_id = 1 + +struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG { + uint32_t opcode; + __gen_address_type address; + uint32_t padded_height_of_output_image_in_uif_blocks; + uint32_t memory_format; +#define MEMORY_FORMAT_RASTER 0 +#define MEMORY_FORMAT_LINEARTILE 1 +#define MEMORY_FORMAT_UB_LINEAR_1_UIF_BLOCK_WIDE 2 +#define MEMORY_FORMAT_UB_LINEAR_2_UIF_BLOCKS_WIDE 3 +#define MEMORY_FORMAT_UIF_NO_XOR 4 +#define MEMORY_FORMAT_UIF_XOR 5 + uint32_t output_image_format; +#define OUTPUT_IMAGE_FORMAT_DEPTH_COMPONENT32F 0 +#define OUTPUT_IMAGE_FORMAT_DEPTH_COMPONENT24 1 +#define OUTPUT_IMAGE_FORMAT_DEPTH_COMPONENT16 2 +#define OUTPUT_IMAGE_FORMAT_DEPTH24_STENCIL8 3 + uint32_t decimate_mode; + uint32_t internal_type; +#define INTERNAL_TYPE_DEPTH_32F 0 +#define INTERNAL_TYPE_DEPTH_24 1 +#define INTERNAL_TYPE_DEPTH_16 2 + uint32_t internal_bpp_ignored; + uint32_t z_stencil_id; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->z_stencil_id, 4, 7) | + __gen_uint(values->sub_id, 0, 3); + + cl[ 2] = __gen_uint(values->decimate_mode, 6, 7) | + __gen_uint(values->internal_type, 2, 5) | + __gen_uint(values->internal_bpp_ignored, 0, 1); + + cl[ 3] = __gen_uint(values->memory_format, 6, 8) | + __gen_uint(values->output_image_format, 0, 5); + + cl[ 4] = __gen_uint(values->padded_height_of_output_image_in_uif_blocks, 1, 13) | + __gen_uint(values->memory_format, 6, 8) >> 8; + + __gen_emit_reloc(data, &values->address); + cl[ 5] = __gen_address_offset(&values->address) | + __gen_uint(values->padded_height_of_output_image_in_uif_blocks, 1, 13) >> 8; + + cl[ 6] = __gen_address_offset(&values->address) >> 8; + + cl[ 7] = __gen_address_offset(&values->address) >> 16; + + cl[ 8] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CONFIG * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 40, 71); + values->padded_height_of_output_image_in_uif_blocks = __gen_unpack_uint(cl, 33, 45); + values->memory_format = __gen_unpack_uint(cl, 30, 32); + values->output_image_format = __gen_unpack_uint(cl, 24, 29); + values->decimate_mode = __gen_unpack_uint(cl, 22, 23); + values->internal_type = __gen_unpack_uint(cl, 18, 21); + values->internal_bpp_ignored = __gen_unpack_uint(cl, 16, 17); + values->z_stencil_id = __gen_unpack_uint(cl, 12, 15); + values->sub_id = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES_opcode 121 +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES_header\ + .opcode = 121, \ + .sub_id = 3 + +struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES { + uint32_t opcode; + uint32_t unused; + float z_clear_value; + uint32_t stencil_vg_mask_clear_value; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->sub_id, 0, 3); + + cl[ 2] = __gen_uint(values->stencil_vg_mask_clear_value, 0, 7); + + + memcpy(&cl[3], &values->z_clear_value, sizeof(values->z_clear_value)); + cl[ 7] = __gen_uint(values->unused, 0, 15); + + cl[ 8] = __gen_uint(values->unused, 0, 15) >> 8; + +} + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_Z_STENCIL_CLEAR_VALUES * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->unused = __gen_unpack_uint(cl, 56, 71); + values->z_clear_value = __gen_unpack_float(cl, 24, 55); + values->stencil_vg_mask_clear_value = __gen_unpack_uint(cl, 16, 23); + values->sub_id = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1_opcode 121 +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1_header\ + .opcode = 121, \ + .sub_id = 4 + +struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1 { + uint32_t opcode; + uint32_t clear_color_next_24_bits; + uint32_t clear_color_low_32_bits; + uint32_t render_target_number; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1 * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->render_target_number, 4, 7) | + __gen_uint(values->sub_id, 0, 3); + + + memcpy(&cl[2], &values->clear_color_low_32_bits, sizeof(values->clear_color_low_32_bits)); + cl[ 6] = __gen_uint(values->clear_color_next_24_bits, 0, 23); + + cl[ 7] = __gen_uint(values->clear_color_next_24_bits, 0, 23) >> 8; + + cl[ 8] = __gen_uint(values->clear_color_next_24_bits, 0, 23) >> 16; + +} + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART1 * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->clear_color_next_24_bits = __gen_unpack_uint(cl, 48, 71); + values->clear_color_low_32_bits = __gen_unpack_uint(cl, 16, 47); + values->render_target_number = __gen_unpack_uint(cl, 12, 15); + values->sub_id = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART2_opcode 121 +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART2_header\ + .opcode = 121, \ + .sub_id = 5 + +struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART2 { + uint32_t opcode; + uint32_t clear_color_mid_high_24_bits; + uint32_t clear_color_mid_low_32_bits; + uint32_t render_target_number; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART2_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART2 * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->render_target_number, 4, 7) | + __gen_uint(values->sub_id, 0, 3); + + + memcpy(&cl[2], &values->clear_color_mid_low_32_bits, sizeof(values->clear_color_mid_low_32_bits)); + cl[ 6] = __gen_uint(values->clear_color_mid_high_24_bits, 0, 23); + + cl[ 7] = __gen_uint(values->clear_color_mid_high_24_bits, 0, 23) >> 8; + + cl[ 8] = __gen_uint(values->clear_color_mid_high_24_bits, 0, 23) >> 16; + +} + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART2_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART2_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART2 * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->clear_color_mid_high_24_bits = __gen_unpack_uint(cl, 48, 71); + values->clear_color_mid_low_32_bits = __gen_unpack_uint(cl, 16, 47); + values->render_target_number = __gen_unpack_uint(cl, 12, 15); + values->sub_id = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART3_opcode 121 +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART3_header\ + .opcode = 121, \ + .sub_id = 6 + +struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART3 { + uint32_t opcode; + uint32_t pad; + uint32_t uif_padded_height_in_uif_blocks; + uint32_t raster_row_stride_or_image_height_in_pixels; + uint32_t clear_color_high_16_bits; + uint32_t render_target_number; + uint32_t sub_id; +}; + +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART3_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART3 * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->render_target_number, 4, 7) | + __gen_uint(values->sub_id, 0, 3); + + cl[ 2] = __gen_uint(values->clear_color_high_16_bits, 0, 15); + + cl[ 3] = __gen_uint(values->clear_color_high_16_bits, 0, 15) >> 8; + + cl[ 4] = __gen_uint(values->raster_row_stride_or_image_height_in_pixels, 0, 15); + + cl[ 5] = __gen_uint(values->raster_row_stride_or_image_height_in_pixels, 0, 15) >> 8; + + cl[ 6] = __gen_uint(values->uif_padded_height_in_uif_blocks, 0, 12); + + cl[ 7] = __gen_uint(values->pad, 5, 15) | + __gen_uint(values->uif_padded_height_in_uif_blocks, 0, 12) >> 8; + + cl[ 8] = __gen_uint(values->pad, 5, 15) >> 8; + +} + +#define V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART3_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART3_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_RENDERING_MODE_CONFIGURATION_CLEAR_COLORS_PART3 * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->pad = __gen_unpack_uint(cl, 61, 71); + values->uif_padded_height_in_uif_blocks = __gen_unpack_uint(cl, 48, 60); + values->raster_row_stride_or_image_height_in_pixels = __gen_unpack_uint(cl, 32, 47); + values->clear_color_high_16_bits = __gen_unpack_uint(cl, 16, 31); + values->render_target_number = __gen_unpack_uint(cl, 12, 15); + values->sub_id = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_TILE_COORDINATES_opcode 124 +#define V3D33_TILE_COORDINATES_header \ + .opcode = 124 + +struct V3D33_TILE_COORDINATES { + uint32_t opcode; + uint32_t tile_row_number; + uint32_t tile_column_number; +}; + +static inline void +V3D33_TILE_COORDINATES_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_COORDINATES * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->tile_column_number, 0, 11); + + cl[ 2] = __gen_uint(values->tile_row_number, 4, 15) | + __gen_uint(values->tile_column_number, 0, 11) >> 8; + + cl[ 3] = __gen_uint(values->tile_row_number, 4, 15) >> 8; + +} + +#define V3D33_TILE_COORDINATES_length 4 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_COORDINATES_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_COORDINATES * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->tile_row_number = __gen_unpack_uint(cl, 20, 31); + values->tile_column_number = __gen_unpack_uint(cl, 8, 19); +} +#endif + + +#define V3D33_MULTICORE_RENDERING_SUPERTILE_CONFIGURATION_opcode 122 +#define V3D33_MULTICORE_RENDERING_SUPERTILE_CONFIGURATION_header\ + .opcode = 122 + +struct V3D33_MULTICORE_RENDERING_SUPERTILE_CONFIGURATION { + uint32_t opcode; + bool supertile_raster_order; + bool multicore_enable; + uint32_t total_frame_height_in_tiles; + uint32_t total_frame_width_in_tiles; + uint32_t total_frame_height_in_supertiles; + uint32_t total_frame_width_in_supertiles; + uint32_t supertile_height_in_tiles_minus_1; + uint32_t supertile_width_in_tiles_minus_1; +}; + +static inline void +V3D33_MULTICORE_RENDERING_SUPERTILE_CONFIGURATION_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_MULTICORE_RENDERING_SUPERTILE_CONFIGURATION * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->supertile_width_in_tiles_minus_1, 0, 7); + + cl[ 2] = __gen_uint(values->supertile_height_in_tiles_minus_1, 0, 7); + + cl[ 3] = __gen_uint(values->total_frame_width_in_supertiles, 0, 7); + + cl[ 4] = __gen_uint(values->total_frame_height_in_supertiles, 0, 7); + + cl[ 5] = __gen_uint(values->total_frame_width_in_tiles, 0, 11); + + cl[ 6] = __gen_uint(values->total_frame_height_in_tiles, 4, 15) | + __gen_uint(values->total_frame_width_in_tiles, 0, 11) >> 8; + + cl[ 7] = __gen_uint(values->total_frame_height_in_tiles, 4, 15) >> 8; + + cl[ 8] = __gen_uint(values->supertile_raster_order, 4, 4) | + __gen_uint(values->multicore_enable, 0, 0); + +} + +#define V3D33_MULTICORE_RENDERING_SUPERTILE_CONFIGURATION_length 9 +#ifdef __gen_unpack_address +static inline void +V3D33_MULTICORE_RENDERING_SUPERTILE_CONFIGURATION_unpack(const uint8_t * restrict cl, + struct V3D33_MULTICORE_RENDERING_SUPERTILE_CONFIGURATION * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->supertile_raster_order = __gen_unpack_uint(cl, 68, 68); + values->multicore_enable = __gen_unpack_uint(cl, 64, 64); + values->total_frame_height_in_tiles = __gen_unpack_uint(cl, 52, 63); + values->total_frame_width_in_tiles = __gen_unpack_uint(cl, 40, 51); + values->total_frame_height_in_supertiles = __gen_unpack_uint(cl, 32, 39); + values->total_frame_width_in_supertiles = __gen_unpack_uint(cl, 24, 31); + values->supertile_height_in_tiles_minus_1 = __gen_unpack_uint(cl, 16, 23); + values->supertile_width_in_tiles_minus_1 = __gen_unpack_uint(cl, 8, 15); +} +#endif + + +#define V3D33_MULTICORE_RENDERING_TILE_LIST_SET_BASE_opcode 123 +#define V3D33_MULTICORE_RENDERING_TILE_LIST_SET_BASE_header\ + .opcode = 123 + +struct V3D33_MULTICORE_RENDERING_TILE_LIST_SET_BASE { + uint32_t opcode; + __gen_address_type address; + uint32_t tile_list_set_number; +}; + +static inline void +V3D33_MULTICORE_RENDERING_TILE_LIST_SET_BASE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_MULTICORE_RENDERING_TILE_LIST_SET_BASE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + __gen_emit_reloc(data, &values->address); + cl[ 1] = __gen_address_offset(&values->address) | + __gen_uint(values->tile_list_set_number, 0, 3); + + cl[ 2] = __gen_address_offset(&values->address) >> 8; + + cl[ 3] = __gen_address_offset(&values->address) >> 16; + + cl[ 4] = __gen_address_offset(&values->address) >> 24; + +} + +#define V3D33_MULTICORE_RENDERING_TILE_LIST_SET_BASE_length 5 +#ifdef __gen_unpack_address +static inline void +V3D33_MULTICORE_RENDERING_TILE_LIST_SET_BASE_unpack(const uint8_t * restrict cl, + struct V3D33_MULTICORE_RENDERING_TILE_LIST_SET_BASE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->address = __gen_unpack_address(cl, 14, 39); + values->tile_list_set_number = __gen_unpack_uint(cl, 8, 11); +} +#endif + + +#define V3D33_TILE_COORDINATES_IMPLICIT_opcode 125 +#define V3D33_TILE_COORDINATES_IMPLICIT_header \ + .opcode = 125 + +struct V3D33_TILE_COORDINATES_IMPLICIT { + uint32_t opcode; +}; + +static inline void +V3D33_TILE_COORDINATES_IMPLICIT_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_COORDINATES_IMPLICIT * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + +} + +#define V3D33_TILE_COORDINATES_IMPLICIT_length 1 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_COORDINATES_IMPLICIT_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_COORDINATES_IMPLICIT * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); +} +#endif + + +#define V3D33_TILE_LIST_INITIAL_BLOCK_SIZE_opcode 126 +#define V3D33_TILE_LIST_INITIAL_BLOCK_SIZE_header\ + .opcode = 126 + +struct V3D33_TILE_LIST_INITIAL_BLOCK_SIZE { + uint32_t opcode; + bool use_auto_chained_tile_lists; + uint32_t size_of_first_block_in_chained_tile_lists; +#define TILE_ALLOCATION_BLOCK_SIZE_64B 0 +#define TILE_ALLOCATION_BLOCK_SIZE_128B 1 +#define TILE_ALLOCATION_BLOCK_SIZE_256B 2 +}; + +static inline void +V3D33_TILE_LIST_INITIAL_BLOCK_SIZE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TILE_LIST_INITIAL_BLOCK_SIZE * restrict values) +{ + cl[ 0] = __gen_uint(values->opcode, 0, 7); + + cl[ 1] = __gen_uint(values->use_auto_chained_tile_lists, 2, 2) | + __gen_uint(values->size_of_first_block_in_chained_tile_lists, 0, 1); + +} + +#define V3D33_TILE_LIST_INITIAL_BLOCK_SIZE_length 2 +#ifdef __gen_unpack_address +static inline void +V3D33_TILE_LIST_INITIAL_BLOCK_SIZE_unpack(const uint8_t * restrict cl, + struct V3D33_TILE_LIST_INITIAL_BLOCK_SIZE * restrict values) +{ + values->opcode = __gen_unpack_uint(cl, 0, 7); + values->use_auto_chained_tile_lists = __gen_unpack_uint(cl, 10, 10); + values->size_of_first_block_in_chained_tile_lists = __gen_unpack_uint(cl, 8, 9); +} +#endif + + +#define V3D33_GL_SHADER_STATE_RECORD_header \ + + +struct V3D33_GL_SHADER_STATE_RECORD { + bool point_size_in_shaded_vertex_data; + bool enable_clipping; + bool vertex_id_read_by_coordinate_shader; + bool instance_id_read_by_coordinate_shader; + bool vertex_id_read_by_vertex_shader; + bool instance_id_read_by_vertex_shader; + bool fragment_shader_does_z_writes; + bool turn_off_early_z_test; + bool coordinate_shader_has_separate_input_and_output_vpm_blocks; + bool vertex_shader_has_separate_input_and_output_vpm_blocks; + bool fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2; + uint32_t number_of_varyings_in_fragment_shader; + uint32_t coordinate_shader_output_vpm_segment_size; + uint32_t coordinate_shader_input_vpm_segment_size; + uint32_t vertex_shader_output_vpm_segment_size; + uint32_t vertex_shader_input_vpm_segment_size; + __gen_address_type address_of_default_attribute_values; + __gen_address_type fragment_shader_code_address; + bool _2_way_threadable; + bool _4_way_threadable; + bool propagate_nans; + __gen_address_type fragment_shader_uniforms_address; + __gen_address_type vertex_shader_code_address; + __gen_address_type vertex_shader_uniforms_address; + __gen_address_type coordinate_shader_code_address; + __gen_address_type coordinate_shader_uniforms_address; +}; + +static inline void +V3D33_GL_SHADER_STATE_RECORD_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_GL_SHADER_STATE_RECORD * restrict values) +{ + cl[ 0] = __gen_uint(values->point_size_in_shaded_vertex_data, 0, 0) | + __gen_uint(values->enable_clipping, 1, 1) | + __gen_uint(values->vertex_id_read_by_coordinate_shader, 2, 2) | + __gen_uint(values->instance_id_read_by_coordinate_shader, 3, 3) | + __gen_uint(values->vertex_id_read_by_vertex_shader, 4, 4) | + __gen_uint(values->instance_id_read_by_vertex_shader, 5, 5) | + __gen_uint(values->fragment_shader_does_z_writes, 6, 6) | + __gen_uint(values->turn_off_early_z_test, 7, 7); + + cl[ 1] = __gen_uint(values->coordinate_shader_has_separate_input_and_output_vpm_blocks, 0, 0) | + __gen_uint(values->vertex_shader_has_separate_input_and_output_vpm_blocks, 1, 1) | + __gen_uint(values->fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2, 2, 2); + + cl[ 2] = __gen_uint(values->number_of_varyings_in_fragment_shader, 0, 7); + + cl[ 3] = 0; + cl[ 4] = __gen_uint(values->coordinate_shader_output_vpm_segment_size, 0, 7); + + cl[ 5] = __gen_uint(values->coordinate_shader_input_vpm_segment_size, 0, 7); + + cl[ 6] = __gen_uint(values->vertex_shader_output_vpm_segment_size, 0, 7); + + cl[ 7] = __gen_uint(values->vertex_shader_input_vpm_segment_size, 0, 7); + + __gen_emit_reloc(data, &values->address_of_default_attribute_values); + cl[ 8] = __gen_address_offset(&values->address_of_default_attribute_values); + + cl[ 9] = __gen_address_offset(&values->address_of_default_attribute_values) >> 8; + + cl[10] = __gen_address_offset(&values->address_of_default_attribute_values) >> 16; + + cl[11] = __gen_address_offset(&values->address_of_default_attribute_values) >> 24; + + __gen_emit_reloc(data, &values->fragment_shader_code_address); + cl[12] = __gen_address_offset(&values->fragment_shader_code_address) | + __gen_uint(values->_2_way_threadable, 0, 0) | + __gen_uint(values->_4_way_threadable, 1, 1) | + __gen_uint(values->propagate_nans, 2, 2); + + cl[13] = __gen_address_offset(&values->fragment_shader_code_address) >> 8; + + cl[14] = __gen_address_offset(&values->fragment_shader_code_address) >> 16; + + cl[15] = __gen_address_offset(&values->fragment_shader_code_address) >> 24; + + __gen_emit_reloc(data, &values->fragment_shader_uniforms_address); + cl[16] = __gen_address_offset(&values->fragment_shader_uniforms_address); + + cl[17] = __gen_address_offset(&values->fragment_shader_uniforms_address) >> 8; + + cl[18] = __gen_address_offset(&values->fragment_shader_uniforms_address) >> 16; + + cl[19] = __gen_address_offset(&values->fragment_shader_uniforms_address) >> 24; + + __gen_emit_reloc(data, &values->vertex_shader_code_address); + cl[20] = __gen_address_offset(&values->vertex_shader_code_address); + + cl[21] = __gen_address_offset(&values->vertex_shader_code_address) >> 8; + + cl[22] = __gen_address_offset(&values->vertex_shader_code_address) >> 16; + + cl[23] = __gen_address_offset(&values->vertex_shader_code_address) >> 24; + + __gen_emit_reloc(data, &values->vertex_shader_uniforms_address); + cl[24] = __gen_address_offset(&values->vertex_shader_uniforms_address); + + cl[25] = __gen_address_offset(&values->vertex_shader_uniforms_address) >> 8; + + cl[26] = __gen_address_offset(&values->vertex_shader_uniforms_address) >> 16; + + cl[27] = __gen_address_offset(&values->vertex_shader_uniforms_address) >> 24; + + __gen_emit_reloc(data, &values->coordinate_shader_code_address); + cl[28] = __gen_address_offset(&values->coordinate_shader_code_address); + + cl[29] = __gen_address_offset(&values->coordinate_shader_code_address) >> 8; + + cl[30] = __gen_address_offset(&values->coordinate_shader_code_address) >> 16; + + cl[31] = __gen_address_offset(&values->coordinate_shader_code_address) >> 24; + + __gen_emit_reloc(data, &values->coordinate_shader_uniforms_address); + cl[32] = __gen_address_offset(&values->coordinate_shader_uniforms_address); + + cl[33] = __gen_address_offset(&values->coordinate_shader_uniforms_address) >> 8; + + cl[34] = __gen_address_offset(&values->coordinate_shader_uniforms_address) >> 16; + + cl[35] = __gen_address_offset(&values->coordinate_shader_uniforms_address) >> 24; + +} + +#define V3D33_GL_SHADER_STATE_RECORD_length 36 +#ifdef __gen_unpack_address +static inline void +V3D33_GL_SHADER_STATE_RECORD_unpack(const uint8_t * restrict cl, + struct V3D33_GL_SHADER_STATE_RECORD * restrict values) +{ + values->point_size_in_shaded_vertex_data = __gen_unpack_uint(cl, 0, 0); + values->enable_clipping = __gen_unpack_uint(cl, 1, 1); + values->vertex_id_read_by_coordinate_shader = __gen_unpack_uint(cl, 2, 2); + values->instance_id_read_by_coordinate_shader = __gen_unpack_uint(cl, 3, 3); + values->vertex_id_read_by_vertex_shader = __gen_unpack_uint(cl, 4, 4); + values->instance_id_read_by_vertex_shader = __gen_unpack_uint(cl, 5, 5); + values->fragment_shader_does_z_writes = __gen_unpack_uint(cl, 6, 6); + values->turn_off_early_z_test = __gen_unpack_uint(cl, 7, 7); + values->coordinate_shader_has_separate_input_and_output_vpm_blocks = __gen_unpack_uint(cl, 8, 8); + values->vertex_shader_has_separate_input_and_output_vpm_blocks = __gen_unpack_uint(cl, 9, 9); + values->fragment_shader_uses_real_pixel_centre_w_in_addition_to_centroid_w2 = __gen_unpack_uint(cl, 10, 10); + values->number_of_varyings_in_fragment_shader = __gen_unpack_uint(cl, 16, 23); + values->coordinate_shader_output_vpm_segment_size = __gen_unpack_uint(cl, 32, 39); + values->coordinate_shader_input_vpm_segment_size = __gen_unpack_uint(cl, 40, 47); + values->vertex_shader_output_vpm_segment_size = __gen_unpack_uint(cl, 48, 55); + values->vertex_shader_input_vpm_segment_size = __gen_unpack_uint(cl, 56, 63); + values->address_of_default_attribute_values = __gen_unpack_address(cl, 64, 95); + values->fragment_shader_code_address = __gen_unpack_address(cl, 99, 127); + values->_2_way_threadable = __gen_unpack_uint(cl, 96, 96); + values->_4_way_threadable = __gen_unpack_uint(cl, 97, 97); + values->propagate_nans = __gen_unpack_uint(cl, 98, 98); + values->fragment_shader_uniforms_address = __gen_unpack_address(cl, 128, 159); + values->vertex_shader_code_address = __gen_unpack_address(cl, 160, 191); + values->vertex_shader_uniforms_address = __gen_unpack_address(cl, 192, 223); + values->coordinate_shader_code_address = __gen_unpack_address(cl, 224, 255); + values->coordinate_shader_uniforms_address = __gen_unpack_address(cl, 256, 287); +} +#endif + + +#define V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD_header\ + + +struct V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD { + __gen_address_type address; + uint32_t vec_size; + uint32_t type; +#define ATTRIBUTE_HALF_FLOAT 1 +#define ATTRIBUTE_FLOAT 2 +#define ATTRIBUTE_FIXED 3 +#define ATTRIBUTE_BYTE 4 +#define ATTRIBUTE_SHORT 5 +#define ATTRIBUTE_INT 6 +#define ATTRIBUTE_INT2_10_10_10 7 + bool signed_int_type; + bool normalized_int_type; + bool read_as_int_uint; + uint32_t number_of_values_read_by_coordinate_shader; + uint32_t number_of_values_read_by_vertex_shader; + uint32_t instance_divisor; + uint32_t stride; +}; + +static inline void +V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD * restrict values) +{ + __gen_emit_reloc(data, &values->address); + cl[ 0] = __gen_address_offset(&values->address); + + cl[ 1] = __gen_address_offset(&values->address) >> 8; + + cl[ 2] = __gen_address_offset(&values->address) >> 16; + + cl[ 3] = __gen_address_offset(&values->address) >> 24; + + cl[ 4] = __gen_uint(values->vec_size, 0, 1) | + __gen_uint(values->type, 2, 4) | + __gen_uint(values->signed_int_type, 5, 5) | + __gen_uint(values->normalized_int_type, 6, 6) | + __gen_uint(values->read_as_int_uint, 7, 7); + + cl[ 5] = __gen_uint(values->number_of_values_read_by_coordinate_shader, 0, 3) | + __gen_uint(values->number_of_values_read_by_vertex_shader, 4, 7); + + cl[ 6] = __gen_uint(values->instance_divisor, 0, 15); + + cl[ 7] = __gen_uint(values->instance_divisor, 0, 15) >> 8; + + + memcpy(&cl[8], &values->stride, sizeof(values->stride)); +} + +#define V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD_length 12 +#ifdef __gen_unpack_address +static inline void +V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD_unpack(const uint8_t * restrict cl, + struct V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD * restrict values) +{ + values->address = __gen_unpack_address(cl, 0, 31); + values->vec_size = __gen_unpack_uint(cl, 32, 33); + values->type = __gen_unpack_uint(cl, 34, 36); + values->signed_int_type = __gen_unpack_uint(cl, 37, 37); + values->normalized_int_type = __gen_unpack_uint(cl, 38, 38); + values->read_as_int_uint = __gen_unpack_uint(cl, 39, 39); + values->number_of_values_read_by_coordinate_shader = __gen_unpack_uint(cl, 40, 43); + values->number_of_values_read_by_vertex_shader = __gen_unpack_uint(cl, 44, 47); + values->instance_divisor = __gen_unpack_uint(cl, 48, 63); + values->stride = __gen_unpack_uint(cl, 64, 95); +} +#endif + + +#define V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP_header\ + .id = 0, \ + .id0 = 0 + +struct V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP { + uint32_t id; + uint32_t id0; + bool horiz; + bool laned; + bool segs; + int32_t stride; + uint32_t size; +#define VPM_SETUP_SIZE_8_BIT 0 +#define VPM_SETUP_SIZE_16_BIT 1 +#define VPM_SETUP_SIZE_32_BIT 2 + uint32_t addr; +}; + +static inline void +V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP * restrict values) +{ + cl[ 0] = __gen_uint(values->addr, 0, 12); + + cl[ 1] = __gen_sint(values->stride, 7, 13) | + __gen_uint(values->size, 5, 6) | + __gen_uint(values->addr, 0, 12) >> 8; + + cl[ 2] = __gen_uint(values->laned, 7, 7) | + __gen_uint(values->segs, 6, 6) | + __gen_sint(values->stride, 7, 13) >> 8; + + cl[ 3] = __gen_uint(values->id, 6, 7) | + __gen_uint(values->id0, 3, 5) | + __gen_uint(values->horiz, 0, 0); + +} + +#define V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP_length 4 +#ifdef __gen_unpack_address +static inline void +V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP_unpack(const uint8_t * restrict cl, + struct V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP * restrict values) +{ + values->id = __gen_unpack_uint(cl, 30, 31); + values->id0 = __gen_unpack_uint(cl, 27, 29); + values->horiz = __gen_unpack_uint(cl, 24, 24); + values->laned = __gen_unpack_uint(cl, 23, 23); + values->segs = __gen_unpack_uint(cl, 22, 22); + values->stride = __gen_unpack_sint(cl, 15, 21); + values->size = __gen_unpack_uint(cl, 13, 14); + values->addr = __gen_unpack_uint(cl, 0, 12); +} +#endif + + +#define V3D33_VPM_GENERIC_BLOCK_READ_SETUP_header\ + .id = 1 + +struct V3D33_VPM_GENERIC_BLOCK_READ_SETUP { + uint32_t id; + bool horiz; + bool laned; + bool segs; + uint32_t num; + int32_t stride; + uint32_t size; +#define VPM_SETUP_SIZE_8_BIT 0 +#define VPM_SETUP_SIZE_16_BIT 1 +#define VPM_SETUP_SIZE_32_BIT 2 + uint32_t addr; +}; + +static inline void +V3D33_VPM_GENERIC_BLOCK_READ_SETUP_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_VPM_GENERIC_BLOCK_READ_SETUP * restrict values) +{ + cl[ 0] = __gen_uint(values->addr, 0, 12); + + cl[ 1] = __gen_sint(values->stride, 7, 13) | + __gen_uint(values->size, 5, 6) | + __gen_uint(values->addr, 0, 12) >> 8; + + cl[ 2] = __gen_uint(values->num, 6, 10) | + __gen_sint(values->stride, 7, 13) >> 8; + + cl[ 3] = __gen_uint(values->id, 6, 7) | + __gen_uint(values->horiz, 5, 5) | + __gen_uint(values->laned, 4, 4) | + __gen_uint(values->segs, 3, 3) | + __gen_uint(values->num, 6, 10) >> 8; + +} + +#define V3D33_VPM_GENERIC_BLOCK_READ_SETUP_length 4 +#ifdef __gen_unpack_address +static inline void +V3D33_VPM_GENERIC_BLOCK_READ_SETUP_unpack(const uint8_t * restrict cl, + struct V3D33_VPM_GENERIC_BLOCK_READ_SETUP * restrict values) +{ + values->id = __gen_unpack_uint(cl, 30, 31); + values->horiz = __gen_unpack_uint(cl, 29, 29); + values->laned = __gen_unpack_uint(cl, 28, 28); + values->segs = __gen_unpack_uint(cl, 27, 27); + values->num = __gen_unpack_uint(cl, 22, 26); + values->stride = __gen_unpack_sint(cl, 15, 21); + values->size = __gen_unpack_uint(cl, 13, 14); + values->addr = __gen_unpack_uint(cl, 0, 12); +} +#endif + + +#define V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_header\ + .new_configuration_mode = 1 + +struct V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1 { + bool per_pixel_mask_enable; + int32_t texel_offset_for_r_coordinate; + int32_t texel_offset_for_t_coordinate; + int32_t texel_offset_for_s_coordinate; + uint32_t r_wrap_mode; +#define WRAP_MODE_REPEAT 0 +#define WRAP_MODE_CLAMP 1 +#define WRAP_MODE_MIRROR 2 +#define WRAP_MODE_BORDER 3 +#define WRAP_MODE_MIRROR_ONCE 4 + uint32_t t_wrap_mode; +#define WRAP_MODE_REPEAT 0 +#define WRAP_MODE_CLAMP 1 +#define WRAP_MODE_MIRROR 2 +#define WRAP_MODE_BORDER 3 +#define WRAP_MODE_MIRROR_ONCE 4 + uint32_t s_wrap_mode; +#define WRAP_MODE_REPEAT 0 +#define WRAP_MODE_CLAMP 1 +#define WRAP_MODE_MIRROR 2 +#define WRAP_MODE_BORDER 3 +#define WRAP_MODE_MIRROR_ONCE 4 + bool new_configuration_mode; + bool shadow; + bool coefficient_lookup_mode; + bool disable_autolod_use_bias_only; + bool bias_supplied; + bool gather_sample_mode; + bool fetch_sample_mode; + bool lookup_type; +#define TEXTURE_2D 0 +#define TEXTURE_2D_ARRAY 1 +#define TEXTURE_3D 2 +#define TEXTURE_CUBE_MAP 3 +#define TEXTURE_1D 4 +#define TEXTURE_1D_ARRAY 5 +#define TEXTURE_CHILD_IMAGE 6 +}; + +static inline void +V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1 * restrict values) +{ + cl[ 0] = __gen_uint(values->coefficient_lookup_mode, 7, 7) | + __gen_uint(values->disable_autolod_use_bias_only, 6, 6) | + __gen_uint(values->bias_supplied, 5, 5) | + __gen_uint(values->gather_sample_mode, 4, 4) | + __gen_uint(values->fetch_sample_mode, 3, 3) | + __gen_uint(values->lookup_type, 0, 2); + + cl[ 1] = __gen_uint(values->t_wrap_mode, 5, 7) | + __gen_uint(values->s_wrap_mode, 2, 4) | + __gen_uint(values->new_configuration_mode, 1, 1) | + __gen_uint(values->shadow, 0, 0); + + cl[ 2] = __gen_sint(values->texel_offset_for_t_coordinate, 7, 10) | + __gen_sint(values->texel_offset_for_s_coordinate, 3, 6) | + __gen_uint(values->r_wrap_mode, 0, 2); + + cl[ 3] = __gen_uint(values->per_pixel_mask_enable, 7, 7) | + __gen_sint(values->texel_offset_for_r_coordinate, 3, 6) | + __gen_sint(values->texel_offset_for_t_coordinate, 7, 10) >> 8; + +} + +#define V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_length 4 +#ifdef __gen_unpack_address +static inline void +V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_unpack(const uint8_t * restrict cl, + struct V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1 * restrict values) +{ + values->per_pixel_mask_enable = __gen_unpack_uint(cl, 31, 31); + values->texel_offset_for_r_coordinate = __gen_unpack_sint(cl, 27, 30); + values->texel_offset_for_t_coordinate = __gen_unpack_sint(cl, 23, 26); + values->texel_offset_for_s_coordinate = __gen_unpack_sint(cl, 19, 22); + values->r_wrap_mode = __gen_unpack_uint(cl, 16, 18); + values->t_wrap_mode = __gen_unpack_uint(cl, 13, 15); + values->s_wrap_mode = __gen_unpack_uint(cl, 10, 12); + values->new_configuration_mode = __gen_unpack_uint(cl, 9, 9); + values->shadow = __gen_unpack_uint(cl, 8, 8); + values->coefficient_lookup_mode = __gen_unpack_uint(cl, 7, 7); + values->disable_autolod_use_bias_only = __gen_unpack_uint(cl, 6, 6); + values->bias_supplied = __gen_unpack_uint(cl, 5, 5); + values->gather_sample_mode = __gen_unpack_uint(cl, 4, 4); + values->fetch_sample_mode = __gen_unpack_uint(cl, 3, 3); + values->lookup_type = __gen_unpack_uint(cl, 0, 2); +} +#endif + + +#define V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_header\ + + +struct V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1 { + __gen_address_type texture_state_record_base_address; + bool return_word_3_of_texture_data; + bool return_word_2_of_texture_data; + bool return_word_1_of_texture_data; + bool return_word_0_of_texture_data; +}; + +static inline void +V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1 * restrict values) +{ + __gen_emit_reloc(data, &values->texture_state_record_base_address); + cl[ 0] = __gen_address_offset(&values->texture_state_record_base_address) | + __gen_uint(values->return_word_3_of_texture_data, 3, 3) | + __gen_uint(values->return_word_2_of_texture_data, 2, 2) | + __gen_uint(values->return_word_1_of_texture_data, 1, 1) | + __gen_uint(values->return_word_0_of_texture_data, 0, 0); + + cl[ 1] = __gen_address_offset(&values->texture_state_record_base_address) >> 8; + + cl[ 2] = __gen_address_offset(&values->texture_state_record_base_address) >> 16; + + cl[ 3] = __gen_address_offset(&values->texture_state_record_base_address) >> 24; + +} + +#define V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_length 4 +#ifdef __gen_unpack_address +static inline void +V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_unpack(const uint8_t * restrict cl, + struct V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1 * restrict values) +{ + values->texture_state_record_base_address = __gen_unpack_address(cl, 0, 31); + values->return_word_3_of_texture_data = __gen_unpack_uint(cl, 3, 3); + values->return_word_2_of_texture_data = __gen_unpack_uint(cl, 2, 2); + values->return_word_1_of_texture_data = __gen_unpack_uint(cl, 1, 1); + values->return_word_0_of_texture_data = __gen_unpack_uint(cl, 0, 0); +} +#endif + + +#define V3D33_TEXTURE_SHADER_STATE_header \ + .flip_etc_y = 1 + +struct V3D33_TEXTURE_SHADER_STATE { + bool level_0_is_strictly_uif; + bool level_0_xor_enable; + uint32_t level_0_ub_pad; + uint32_t base_level; + float fixed_bias; + float max_level_of_detail; + float min_level_of_detail; + uint32_t border_color_alpha; + uint32_t border_color_blue; + uint32_t border_color_green; + uint32_t border_color_red; + bool flip_s_and_t_on_incoming_request; + bool flip_etc_y; + bool flip_texture_y_axis; + bool flip_texture_x_axis; + uint32_t swizzle_a; +#define SWIZZLE_ZERO 0 +#define SWIZZLE_ONE 1 +#define SWIZZLE_RED 2 +#define SWIZZLE_GREEN 3 +#define SWIZZLE_BLUE 4 +#define SWIZZLE_ALPHA 5 + uint32_t swizzle_b; + uint32_t swizzle_g; + uint32_t swizzle_r; + enum V3D33_Compare_Function depth_compare_function; + bool srgb; + uint32_t texture_type; + uint32_t image_depth; + uint32_t image_height; + uint32_t image_width; + uint32_t array_stride_64_byte_aligned; + __gen_address_type texture_base_pointer; + uint32_t minification_filter; + uint32_t magnification_filter; +}; + +static inline void +V3D33_TEXTURE_SHADER_STATE_pack(__gen_user_data *data, uint8_t * restrict cl, + const struct V3D33_TEXTURE_SHADER_STATE * restrict values) +{ + __gen_emit_reloc(data, &values->texture_base_pointer); + cl[ 0] = __gen_address_offset(&values->texture_base_pointer) | + __gen_uint(values->minification_filter, 1, 3) | + __gen_uint(values->magnification_filter, 0, 0); + + cl[ 1] = __gen_address_offset(&values->texture_base_pointer) >> 8; + + cl[ 2] = __gen_address_offset(&values->texture_base_pointer) >> 16; + + cl[ 3] = __gen_address_offset(&values->texture_base_pointer) >> 24; + + cl[ 4] = __gen_uint(values->array_stride_64_byte_aligned, 0, 25); + + cl[ 5] = __gen_uint(values->array_stride_64_byte_aligned, 0, 25) >> 8; + + cl[ 6] = __gen_uint(values->array_stride_64_byte_aligned, 0, 25) >> 16; + + cl[ 7] = __gen_uint(values->image_width, 2, 15) | + __gen_uint(values->array_stride_64_byte_aligned, 0, 25) >> 24; + + cl[ 8] = __gen_uint(values->image_width, 2, 15) >> 8; + + cl[ 9] = __gen_uint(values->image_height, 0, 13); + + cl[10] = __gen_uint(values->image_depth, 6, 19) | + __gen_uint(values->image_height, 0, 13) >> 8; + + cl[11] = __gen_uint(values->image_depth, 6, 19) >> 8; + + cl[12] = __gen_uint(values->texture_type, 4, 10) | + __gen_uint(values->image_depth, 6, 19) >> 16; + + cl[13] = __gen_uint(values->depth_compare_function, 5, 7) | + __gen_uint(values->srgb, 3, 3) | + __gen_uint(values->texture_type, 4, 10) >> 8; + + cl[14] = __gen_uint(values->swizzle_b, 6, 8) | + __gen_uint(values->swizzle_g, 3, 5) | + __gen_uint(values->swizzle_r, 0, 2); + + cl[15] = __gen_uint(values->flip_s_and_t_on_incoming_request, 7, 7) | + __gen_uint(values->flip_etc_y, 6, 6) | + __gen_uint(values->flip_texture_y_axis, 5, 5) | + __gen_uint(values->flip_texture_x_axis, 4, 4) | + __gen_uint(values->swizzle_a, 1, 3) | + __gen_uint(values->swizzle_b, 6, 8) >> 8; + + cl[16] = __gen_uint(values->border_color_red, 0, 15); + + cl[17] = __gen_uint(values->border_color_red, 0, 15) >> 8; + + cl[18] = __gen_uint(values->border_color_green, 0, 15); + + cl[19] = __gen_uint(values->border_color_green, 0, 15) >> 8; + + cl[20] = __gen_uint(values->border_color_blue, 0, 15); + + cl[21] = __gen_uint(values->border_color_blue, 0, 15) >> 8; + + cl[22] = __gen_uint(values->border_color_alpha, 0, 15); + + cl[23] = __gen_uint(values->border_color_alpha, 0, 15) >> 8; + + cl[24] = __gen_sfixed(values->min_level_of_detail, 0, 15, 8); + + cl[25] = __gen_sfixed(values->min_level_of_detail, 0, 15, 8) >> 8; + + cl[26] = __gen_sfixed(values->max_level_of_detail, 0, 15, 8); + + cl[27] = __gen_sfixed(values->max_level_of_detail, 0, 15, 8) >> 8; + + cl[28] = __gen_sfixed(values->fixed_bias, 0, 15, 8); + + cl[29] = __gen_sfixed(values->fixed_bias, 0, 15, 8) >> 8; + + cl[30] = __gen_uint(values->base_level, 0, 3); + + cl[31] = __gen_uint(values->level_0_is_strictly_uif, 6, 6) | + __gen_uint(values->level_0_xor_enable, 4, 4) | + __gen_uint(values->level_0_ub_pad, 0, 3); + +} + +#define V3D33_TEXTURE_SHADER_STATE_length 32 +#ifdef __gen_unpack_address +static inline void +V3D33_TEXTURE_SHADER_STATE_unpack(const uint8_t * restrict cl, + struct V3D33_TEXTURE_SHADER_STATE * restrict values) +{ + values->level_0_is_strictly_uif = __gen_unpack_uint(cl, 254, 254); + values->level_0_xor_enable = __gen_unpack_uint(cl, 252, 252); + values->level_0_ub_pad = __gen_unpack_uint(cl, 248, 251); + values->base_level = __gen_unpack_uint(cl, 240, 243); + values->fixed_bias = __gen_unpack_sfixed(cl, 224, 239, 8); + values->max_level_of_detail = __gen_unpack_sfixed(cl, 208, 223, 8); + values->min_level_of_detail = __gen_unpack_sfixed(cl, 192, 207, 8); + values->border_color_alpha = __gen_unpack_uint(cl, 176, 191); + values->border_color_blue = __gen_unpack_uint(cl, 160, 175); + values->border_color_green = __gen_unpack_uint(cl, 144, 159); + values->border_color_red = __gen_unpack_uint(cl, 128, 143); + values->flip_s_and_t_on_incoming_request = __gen_unpack_uint(cl, 127, 127); + values->flip_etc_y = __gen_unpack_uint(cl, 126, 126); + values->flip_texture_y_axis = __gen_unpack_uint(cl, 125, 125); + values->flip_texture_x_axis = __gen_unpack_uint(cl, 124, 124); + values->swizzle_a = __gen_unpack_uint(cl, 121, 123); + values->swizzle_b = __gen_unpack_uint(cl, 118, 120); + values->swizzle_g = __gen_unpack_uint(cl, 115, 117); + values->swizzle_r = __gen_unpack_uint(cl, 112, 114); + values->depth_compare_function = __gen_unpack_uint(cl, 109, 111); + values->srgb = __gen_unpack_uint(cl, 107, 107); + values->texture_type = __gen_unpack_uint(cl, 100, 106); + values->image_depth = __gen_unpack_uint(cl, 86, 99); + values->image_height = __gen_unpack_uint(cl, 72, 85); + values->image_width = __gen_unpack_uint(cl, 58, 71); + values->array_stride_64_byte_aligned = __gen_unpack_uint(cl, 32, 57); + values->texture_base_pointer = __gen_unpack_address(cl, 0, 31); + values->minification_filter = __gen_unpack_uint(cl, 1, 3); + values->magnification_filter = __gen_unpack_uint(cl, 0, 0); +} +#endif + + +enum V3D33_Texture_Data_Formats { + TEXTURE_DATA_FORMAT_R8 = 0, + TEXTURE_DATA_FORMAT_R8_SNORM = 1, + TEXTURE_DATA_FORMAT_RG8 = 2, + TEXTURE_DATA_FORMAT_RG8_SNORM = 3, + TEXTURE_DATA_FORMAT_RGBA8 = 4, + TEXTURE_DATA_FORMAT_RGBA8_SNORM = 5, + TEXTURE_DATA_FORMAT_RGB565 = 6, + TEXTURE_DATA_FORMAT_RGBA4 = 7, + TEXTURE_DATA_FORMAT_RGB5_A1 = 8, + TEXTURE_DATA_FORMAT_RGB10_A2 = 9, + TEXTURE_DATA_FORMAT_R16 = 10, + TEXTURE_DATA_FORMAT_R16_SNORM = 11, + TEXTURE_DATA_FORMAT_RG16 = 12, + TEXTURE_DATA_FORMAT_RG16_SNORM = 13, + TEXTURE_DATA_FORMAT_RGBA16 = 14, + TEXTURE_DATA_FORMAT_RGBA16_SNORM = 15, + TEXTURE_DATA_FORMAT_R16F = 16, + TEXTURE_DATA_FORMAT_RG16F = 17, + TEXTURE_DATA_FORMAT_RGBA16F = 18, + TEXTURE_DATA_FORMAT_R11F_G11F_B10F = 19, + TEXTURE_DATA_FORMAT_RGB9_E5 = 20, + TEXTURE_DATA_FORMAT_DEPTH_COMP16 = 21, + TEXTURE_DATA_FORMAT_DEPTH_COMP24 = 22, + TEXTURE_DATA_FORMAT_DEPTH_COMP32F = 23, + TEXTURE_DATA_FORMAT_DEPTH24_X8 = 24, + TEXTURE_DATA_FORMAT_R4 = 25, + TEXTURE_DATA_FORMAT_R1 = 26, + TEXTURE_DATA_FORMAT_S8 = 27, + TEXTURE_DATA_FORMAT_S16 = 28, + TEXTURE_DATA_FORMAT_R32F = 29, + TEXTURE_DATA_FORMAT_RG32F = 30, + TEXTURE_DATA_FORMAT_RGBA32F = 31, + TEXTURE_DATA_FORMAT_RGB8_ETC2 = 32, + TEXTURE_DATA_FORMAT_RGB8_PUNCHTHROUGH_ALPHA1 = 33, + TEXTURE_DATA_FORMAT_R11_EAC = 34, + TEXTURE_DATA_FORMAT_SIGNED_R11_EAC = 35, + TEXTURE_DATA_FORMAT_RG11_EAC = 36, + TEXTURE_DATA_FORMAT_SIGNED_RG11_EAC = 37, + TEXTURE_DATA_FORMAT_RGBA8_ETC2_EAC = 38, + TEXTURE_DATA_FORMAT_YCBCR_LUMA = 39, + TEXTURE_DATA_FORMAT_YCBCR_420_CHROMA = 40, + TEXTURE_DATA_FORMAT_BC1 = 48, + TEXTURE_DATA_FORMAT_BC2 = 49, + TEXTURE_DATA_FORMAT_BC3 = 50, + TEXTURE_DATA_FORMAT_ASTC_4X4 = 64, + TEXTURE_DATA_FORMAT_ASTC_5X4 = 65, + TEXTURE_DATA_FORMAT_ASTC_5X5 = 66, + TEXTURE_DATA_FORMAT_ASTC_6X5 = 67, + TEXTURE_DATA_FORMAT_ASTC_6X6 = 68, + TEXTURE_DATA_FORMAT_ASTC_8X5 = 69, + TEXTURE_DATA_FORMAT_ASTC_8X6 = 70, + TEXTURE_DATA_FORMAT_ASTC_8X8 = 71, + TEXTURE_DATA_FORMAT_ASTC_10X5 = 72, + TEXTURE_DATA_FORMAT_ASTC_10X6 = 73, + TEXTURE_DATA_FORMAT_ASTC_10X8 = 74, + TEXTURE_DATA_FORMAT_ASTC_10X10 = 75, + TEXTURE_DATA_FORMAT_ASTC_12X10 = 76, + TEXTURE_DATA_FORMAT_ASTC_12X12 = 77, +}; + +#endif /* V3D33_PACK_H */ diff --git a/lib/mesa/src/broadcom/cle/v3d_xml.h b/lib/mesa/src/broadcom/cle/v3d_xml.h new file mode 100644 index 000000000..a940429c1 --- /dev/null +++ b/lib/mesa/src/broadcom/cle/v3d_xml.h @@ -0,0 +1,719 @@ +static const struct { + uint32_t gen_10; + uint32_t offset; + uint32_t length; +} genxml_files_table[] = { + { 21, 0, 15431 }, + { 33, 15431, 42910 }, +}; + +static const uint8_t compress_genxmls[] = { + 0x78, 0x9c, 0xed, 0x5d, 0x5b, 0x73, 0xe3, 0xb6, 0x92, 0x7e, 0xcf, 0xaf, + 0xc0, 0xce, 0xcb, 0xf1, 0xec, 0xae, 0x62, 0x91, 0xba, 0x58, 0xae, 0x4a, + 0xb2, 0xa5, 0x9b, 0x3d, 0xae, 0x23, 0x5b, 0x5a, 0x49, 0xf6, 0xcc, 0xf8, + 0x45, 0x45, 0x49, 0x94, 0xcd, 0x8a, 0x44, 0xea, 0x90, 0x94, 0x2f, 0xf9, + 0xf5, 0x8b, 0x0b, 0x49, 0x00, 0x64, 0x83, 0x00, 0x35, 0x9e, 0x49, 0xb2, + 0xc7, 0xa7, 0x4e, 0x25, 0x8e, 0xdd, 0x68, 0x00, 0xdd, 0x8d, 0x46, 0xa3, + 0xd1, 0xf8, 0xf8, 0xcb, 0xd3, 0xea, 0x65, 0xb7, 0x45, 0x0f, 0xae, 0xff, + 0xeb, 0x07, 0xfb, 0x67, 0xeb, 0xc3, 0x6f, 0x3f, 0x21, 0xf4, 0xcb, 0xde, + 0x59, 0xfd, 0xee, 0xc6, 0xc8, 0x77, 0x76, 0xee, 0xaf, 0x1f, 0x3e, 0x39, + 0xdb, 0xf8, 0x03, 0x5a, 0x05, 0x6b, 0xfc, 0x73, 0xfd, 0xc3, 0x69, 0x91, + 0xe0, 0x66, 0x3c, 0x49, 0xff, 0x6e, 0x41, 0x7f, 0xbf, 0xd8, 0x1e, 0xa2, + 0xc7, 0x94, 0xa2, 0x89, 0x7f, 0xd8, 0xfe, 0xfa, 0xa1, 0xa7, 0x24, 0x44, + 0xdd, 0xed, 0x16, 0xcd, 0x62, 0x27, 0x76, 0xd3, 0x26, 0xad, 0x92, 0x26, + 0x98, 0x30, 0x8c, 0xd1, 0xdc, 0xdb, 0xba, 0xa8, 0xe7, 0xf9, 0xbe, 0xe7, + 0x3f, 0xa4, 0xad, 0xda, 0x25, 0xad, 0xae, 0xfc, 0x55, 0xe8, 0xee, 0x5c, + 0x3f, 0x46, 0x33, 0x77, 0xe7, 0xec, 0x1f, 0x83, 0x30, 0xeb, 0xec, 0x0c, + 0xa2, 0xff, 0xec, 0x78, 0x31, 0x0a, 0xfc, 0x22, 0x75, 0x07, 0xa2, 0xee, + 0x85, 0x8e, 0xbf, 0xca, 0x26, 0x6c, 0xb5, 0xa9, 0x4c, 0x31, 0xd1, 0xc6, + 0x73, 0xb7, 0xeb, 0x84, 0xa6, 0xbb, 0x5e, 0x87, 0x6e, 0x14, 0x7d, 0x40, + 0x91, 0xf7, 0x07, 0xfe, 0xcf, 0x86, 0x8d, 0x7f, 0x22, 0x53, 0x21, 0x22, + 0x46, 0xf1, 0xeb, 0x1e, 0xff, 0xce, 0x49, 0x48, 0x58, 0x0f, 0xa7, 0xac, + 0x0b, 0x55, 0x6f, 0x28, 0x0e, 0x50, 0x74, 0x58, 0xd6, 0xb6, 0x5e, 0x94, + 0x29, 0xcb, 0x3a, 0xfb, 0xbe, 0x3d, 0x4f, 0xdd, 0xf8, 0x10, 0xfa, 0x68, + 0x13, 0x06, 0xbb, 0x62, 0xdf, 0x54, 0x32, 0x80, 0xba, 0xb0, 0xf0, 0xd0, + 0xf5, 0x61, 0x1b, 0x7b, 0xb5, 0xc8, 0xd9, 0xed, 0xb1, 0xda, 0xa6, 0x6e, + 0x14, 0x6c, 0x9f, 0xdc, 0x35, 0x53, 0x62, 0x3f, 0xd8, 0x06, 0x21, 0xea, + 0x1d, 0x36, 0x1b, 0x37, 0x4c, 0x79, 0xd9, 0x89, 0xcd, 0x4c, 0x61, 0x03, + 0xa8, 0xc0, 0x11, 0x39, 0xfe, 0x1a, 0x0d, 0xc7, 0x17, 0x19, 0xe7, 0x96, + 0xc0, 0x59, 0xc1, 0xfa, 0xe2, 0x80, 0xed, 0x91, 0xb2, 0x3c, 0xc4, 0x1e, + 0xb6, 0x01, 0x66, 0x6b, 0xe9, 0x00, 0x69, 0xe3, 0x94, 0x9b, 0x89, 0xa6, + 0xed, 0x4e, 0x26, 0xef, 0x26, 0x28, 0xef, 0x5c, 0xf3, 0x91, 0x13, 0x31, + 0xfb, 0x4e, 0x19, 0x58, 0x59, 0xfb, 0x46, 0xda, 0x7e, 0x19, 0x04, 0x5b, + 0xb0, 0xf1, 0xc0, 0x8b, 0x9c, 0x25, 0x91, 0xc1, 0xd6, 0x75, 0x42, 0x62, + 0xc0, 0x9f, 0x43, 0x2f, 0x06, 0x38, 0xd9, 0xc6, 0x9c, 0xee, 0x4f, 0x67, + 0xb1, 0xeb, 0xaf, 0xbc, 0x6d, 0x2a, 0xd1, 0x67, 0x98, 0xa3, 0x65, 0x3e, + 0x36, 0x51, 0x3f, 0x0a, 0x6e, 0xf5, 0x22, 0x37, 0x6e, 0x96, 0x80, 0x5d, + 0xd6, 0xb6, 0x81, 0xb3, 0xae, 0xa2, 0x39, 0x93, 0x95, 0x52, 0x55, 0x73, + 0x4a, 0x91, 0x85, 0xae, 0xb3, 0x7e, 0x33, 0x89, 0xc1, 0xcc, 0xaa, 0x09, + 0x8c, 0x19, 0xba, 0x20, 0x1e, 0x74, 0xe9, 0xfa, 0x6e, 0xe8, 0x6c, 0x33, + 0xf9, 0x74, 0x52, 0x81, 0x01, 0xc3, 0xba, 0x76, 0x77, 0x41, 0xf8, 0x8a, + 0x96, 0x4e, 0xe4, 0xa2, 0x44, 0x1e, 0x28, 0xd8, 0x60, 0xb7, 0x80, 0xff, + 0x7a, 0x1a, 0x13, 0xa6, 0xeb, 0xc3, 0x6e, 0x8f, 0x96, 0x89, 0xe0, 0x0b, + 0xc2, 0xb4, 0x61, 0xbf, 0xa3, 0x5a, 0x07, 0x84, 0xf7, 0x05, 0xe1, 0x0d, + 0x88, 0xf0, 0xdc, 0x58, 0x86, 0x77, 0x97, 0xb5, 0x6b, 0x27, 0xfa, 0x3d, + 0x19, 0x15, 0x1d, 0x21, 0xc0, 0xaf, 0x73, 0xc4, 0xba, 0x28, 0xe7, 0x78, + 0x56, 0x51, 0xcb, 0xe5, 0xdc, 0xda, 0xc7, 0xce, 0x77, 0x95, 0x3a, 0x84, + 0x88, 0xa8, 0xfe, 0x54, 0xc1, 0xbe, 0x75, 0xfc, 0xf4, 0xcd, 0x3a, 0x68, + 0x1e, 0x27, 0x0d, 0x33, 0xe6, 0x05, 0xf7, 0x58, 0xe4, 0x3e, 0xf1, 0x5e, + 0xdc, 0x6d, 0xc2, 0xfb, 0x22, 0x08, 0x77, 0x4e, 0x9c, 0xd9, 0x67, 0xc6, + 0x27, 0xb3, 0x81, 0x83, 0xe7, 0xc7, 0x89, 0xfd, 0x63, 0x36, 0x4f, 0xce, + 0xf6, 0xe0, 0x26, 0x6c, 0xc2, 0x87, 0xa5, 0xd3, 0xc1, 0xff, 0xfb, 0x80, + 0xe8, 0x6f, 0xb3, 0x30, 0xa9, 0x40, 0xb8, 0x7c, 0x08, 0x5b, 0xed, 0x16, + 0x5a, 0x7b, 0xf1, 0xa3, 0x1b, 0xba, 0xeb, 0x8c, 0xde, 0x2a, 0xa7, 0xf7, + 0x83, 0xa4, 0x49, 0xd6, 0xc0, 0xce, 0x84, 0x75, 0x4a, 0xe7, 0x03, 0x4d, + 0xee, 0x1a, 0x2f, 0xdd, 0xe2, 0x74, 0xda, 0xfa, 0xe9, 0xcc, 0xd8, 0x36, + 0x5a, 0xd7, 0x4e, 0x67, 0xe0, 0xae, 0x3c, 0x2c, 0x33, 0x17, 0xbd, 0x34, + 0xb5, 0x53, 0xe1, 0xb4, 0xc4, 0x6a, 0x2b, 0x4c, 0x43, 0xa5, 0x97, 0xa6, + 0x7e, 0x22, 0x53, 0xec, 0x33, 0x04, 0xa1, 0xa9, 0xa6, 0x31, 0xd7, 0x0e, + 0x7e, 0x34, 0xaf, 0x34, 0xe4, 0xc4, 0x89, 0xe2, 0x90, 0x8c, 0x7a, 0xd6, + 0x2c, 0xd4, 0x2a, 0xba, 0x67, 0xf5, 0xd8, 0x6f, 0x02, 0xdf, 0xd5, 0x8e, + 0x9c, 0x5a, 0xae, 0x76, 0xf4, 0xf7, 0xa7, 0x11, 0x5b, 0x9c, 0xc5, 0x49, + 0xe4, 0x29, 0x33, 0x8a, 0x86, 0x82, 0x22, 0xf1, 0x23, 0x19, 0x5d, 0xb3, + 0x20, 0x8e, 0xd2, 0x9d, 0x66, 0x44, 0xf6, 0xe5, 0xb2, 0x8d, 0xe6, 0xfc, + 0x4f, 0xdf, 0x68, 0x14, 0x1e, 0x93, 0x44, 0x14, 0x6f, 0xbb, 0x43, 0x28, + 0x38, 0x1e, 0xb9, 0x43, 0x28, 0xb8, 0x15, 0x76, 0x88, 0x77, 0x27, 0xf8, + 0xee, 0x04, 0xdf, 0x9d, 0xe0, 0x9f, 0xea, 0x04, 0xaf, 0xfc, 0xb5, 0xfb, + 0x82, 0x8f, 0xa7, 0x93, 0xd0, 0xdb, 0x79, 0xb1, 0xf7, 0xe4, 0xa2, 0x91, + 0x70, 0x72, 0xc6, 0x07, 0x72, 0xc8, 0xf7, 0x39, 0x2f, 0xde, 0xee, 0xb0, + 0x43, 0xb4, 0x2d, 0x70, 0x76, 0x3f, 0xb3, 0x25, 0x69, 0x42, 0x6e, 0xa3, + 0xcb, 0x5d, 0x26, 0xe6, 0xe2, 0xad, 0xdc, 0x28, 0xe9, 0xb7, 0xc0, 0xac, + 0x59, 0xd7, 0x32, 0x1b, 0xb9, 0xfe, 0x43, 0xfc, 0x08, 0xb4, 0xed, 0x68, + 0x9b, 0xd2, 0x29, 0x50, 0xa2, 0xb4, 0x79, 0xb3, 0x8a, 0x3d, 0x77, 0x6a, + 0x4b, 0x2f, 0xd6, 0x1a, 0x85, 0xd5, 0x96, 0xc8, 0x2c, 0x40, 0x43, 0x79, + 0x37, 0x98, 0x69, 0x63, 0x27, 0xf8, 0x8c, 0x66, 0x15, 0x73, 0xdd, 0x07, + 0xf8, 0x4f, 0x91, 0x76, 0x6c, 0x5b, 0xcf, 0x77, 0x23, 0xad, 0xc1, 0x12, + 0x2a, 0xec, 0xd5, 0x83, 0xbd, 0xd6, 0x60, 0x29, 0x65, 0x14, 0x87, 0xde, + 0x5e, 0x6b, 0xb9, 0x98, 0xc8, 0xf1, 0x1f, 0xb6, 0x42, 0xf7, 0x4d, 0x1d, + 0x65, 0x8e, 0x73, 0x4b, 0x4b, 0xbf, 0x71, 0xfc, 0x8c, 0xba, 0x5d, 0x6d, + 0x65, 0xdc, 0xb9, 0x61, 0x8c, 0x6d, 0xa3, 0x1b, 0x86, 0xce, 0x2b, 0x5f, + 0x1e, 0x51, 0xb6, 0x34, 0x1a, 0xd0, 0xd2, 0x60, 0xf6, 0x44, 0x4e, 0x85, + 0x5e, 0x88, 0xcf, 0x88, 0x8c, 0xc7, 0x0f, 0xb7, 0xea, 0x77, 0xf3, 0xf9, + 0xf3, 0xcd, 0x47, 0x76, 0xa8, 0x59, 0x30, 0x23, 0xa5, 0x7a, 0x5a, 0x60, + 0x92, 0x6e, 0xe0, 0xc4, 0x0e, 0x9a, 0x1f, 0xeb, 0x92, 0x98, 0xb3, 0x41, + 0x1e, 0xf3, 0xcd, 0x1a, 0xc5, 0x34, 0x6c, 0x4a, 0xfc, 0x72, 0xfa, 0x5a, + 0x14, 0x77, 0xc9, 0x76, 0xca, 0xe7, 0x06, 0x0f, 0xd3, 0xc0, 0xbe, 0x26, + 0xd4, 0xbe, 0x12, 0xa7, 0xaf, 0x31, 0xb2, 0x11, 0x31, 0x32, 0x99, 0x54, + 0x35, 0xa1, 0x79, 0xa6, 0x3a, 0x89, 0x5c, 0x65, 0x6e, 0xd3, 0x4f, 0x5f, + 0x65, 0xc2, 0xe2, 0xec, 0x4b, 0x95, 0x7c, 0x39, 0x42, 0xb3, 0x47, 0x67, + 0x8d, 0x43, 0x0b, 0xe9, 0x92, 0xa0, 0xdd, 0x4c, 0xf5, 0xfa, 0x1f, 0xb5, + 0x1a, 0x9a, 0x3f, 0xf2, 0x23, 0x02, 0x93, 0xe2, 0xb3, 0xb7, 0xc5, 0x91, + 0xb7, 0x8b, 0xff, 0x6b, 0xbb, 0xc5, 0x7b, 0xaf, 0xe7, 0xa3, 0xe5, 0x2b, + 0xfa, 0xdd, 0x0d, 0x7d, 0x1c, 0xfb, 0xe2, 0x81, 0x78, 0x6b, 0x87, 0xe6, + 0x08, 0x09, 0xb3, 0x9f, 0x51, 0xad, 0x56, 0x29, 0x1d, 0xa8, 0x77, 0x2c, + 0xc3, 0x17, 0x1c, 0x7c, 0xac, 0x71, 0xbf, 0x11, 0x1b, 0x7a, 0xe8, 0xae, + 0x82, 0x10, 0x88, 0xd7, 0xf5, 0x29, 0xdd, 0x9b, 0xc3, 0x6e, 0x89, 0x19, + 0x60, 0x77, 0xe7, 0xc4, 0x78, 0xd1, 0x2c, 0x0f, 0x38, 0x9a, 0x74, 0x88, + 0xbf, 0x8c, 0x74, 0x11, 0x96, 0x2e, 0x0b, 0xc8, 0x92, 0xc4, 0x34, 0x9a, + 0x8a, 0x72, 0x8b, 0xc6, 0xb2, 0x9a, 0xd0, 0xaa, 0x61, 0x2d, 0x66, 0x69, + 0x5c, 0xc5, 0xba, 0xe7, 0x62, 0x39, 0x6f, 0x6b, 0xe5, 0xc2, 0x38, 0xdc, + 0x5d, 0x22, 0x16, 0x4f, 0xe5, 0x39, 0x74, 0xf4, 0x7e, 0x97, 0x71, 0xb8, + 0x9f, 0x65, 0x6a, 0xe1, 0x4b, 0xa2, 0xdd, 0x34, 0x6c, 0x9d, 0x44, 0x90, + 0x8c, 0x41, 0x5b, 0xb5, 0xa6, 0xb4, 0xf2, 0x0b, 0xfc, 0x8d, 0xf7, 0x70, + 0x08, 0x99, 0x21, 0xf5, 0xbc, 0x38, 0xdb, 0xb7, 0xce, 0x41, 0x9f, 0x33, + 0x74, 0xc2, 0xed, 0x2b, 0xba, 0x47, 0x87, 0x3d, 0xb6, 0x3d, 0xbc, 0x7a, + 0x5c, 0x9f, 0x9c, 0xea, 0x8e, 0x3a, 0x11, 0xa6, 0xac, 0x94, 0x2c, 0xf4, + 0x89, 0x42, 0x83, 0x71, 0x18, 0xa4, 0x03, 0xdd, 0x7d, 0xfc, 0x58, 0x9b, + 0xbb, 0xc4, 0xf9, 0x1e, 0xfc, 0x15, 0x11, 0x44, 0xd1, 0x2a, 0x2d, 0x38, + 0x54, 0x25, 0xcb, 0x16, 0x2f, 0x59, 0xe6, 0x15, 0x22, 0x78, 0x09, 0xf6, + 0x83, 0x27, 0x37, 0x74, 0x1e, 0xc8, 0x15, 0x8f, 0xb3, 0x46, 0xe2, 0xd9, + 0x4e, 0x18, 0xa6, 0xf5, 0xed, 0xec, 0x27, 0xde, 0xde, 0x45, 0x33, 0x77, + 0xeb, 0xae, 0xe2, 0x62, 0x07, 0xfa, 0x23, 0x3f, 0x3b, 0x72, 0x79, 0x11, + 0x5e, 0xa7, 0x63, 0xcc, 0x31, 0xb9, 0x96, 0xd2, 0x1c, 0x45, 0x25, 0x6e, + 0xd5, 0x85, 0x21, 0xee, 0x0a, 0x7c, 0xac, 0xad, 0xa3, 0x65, 0xd1, 0xf5, + 0x63, 0x0f, 0xbb, 0x45, 0x27, 0x22, 0x07, 0x15, 0xb6, 0x71, 0x90, 0xcb, + 0xb3, 0x11, 0x0b, 0x3e, 0xf2, 0xfd, 0xe8, 0x13, 0xb9, 0x43, 0x6a, 0x55, + 0x88, 0x5a, 0x08, 0x1a, 0x6f, 0x36, 0x91, 0x0b, 0x88, 0x56, 0xef, 0xfe, + 0xfa, 0xdb, 0x60, 0xf5, 0xfb, 0x33, 0x16, 0xad, 0x14, 0x1e, 0x56, 0xbf, + 0xcf, 0x4a, 0x86, 0x33, 0x75, 0x89, 0x7e, 0x5c, 0x74, 0xe1, 0xac, 0x3c, + 0xff, 0x81, 0xf3, 0x3c, 0xe6, 0x7a, 0x26, 0x61, 0x89, 0xa3, 0x8e, 0x67, + 0x27, 0x5c, 0x1b, 0xb0, 0xac, 0x76, 0x49, 0x73, 0xb1, 0x75, 0x62, 0xb6, + 0xf3, 0x21, 0xfc, 0xe3, 0x03, 0x77, 0x2e, 0xe0, 0xdd, 0x15, 0xa1, 0xae, + 0x91, 0xcd, 0x86, 0x8c, 0x21, 0xa1, 0x57, 0x5f, 0xf8, 0x1a, 0xf9, 0x37, + 0x6a, 0x05, 0x94, 0x49, 0xd6, 0x75, 0x07, 0xea, 0x9a, 0xd1, 0xcd, 0x28, + 0x9d, 0xba, 0xcb, 0xcd, 0x36, 0x70, 0xf4, 0x7d, 0x12, 0x73, 0xc3, 0x5b, + 0xf7, 0x3a, 0xce, 0xae, 0xd3, 0xcf, 0xcf, 0xa1, 0x3e, 0x45, 0xba, 0x6f, + 0xed, 0x73, 0xfa, 0x69, 0x8e, 0xbe, 0xa0, 0x65, 0x70, 0xf0, 0xd7, 0x4e, + 0xf8, 0x9a, 0x6d, 0x81, 0xf5, 0x3a, 0xd4, 0x31, 0x21, 0xde, 0x67, 0xa1, + 0x99, 0xd8, 0x2c, 0xd1, 0x76, 0xbb, 0x38, 0x0c, 0x13, 0x61, 0xcb, 0xeb, + 0x24, 0x1d, 0x82, 0x25, 0xc6, 0x38, 0xf1, 0xa3, 0x1b, 0xb9, 0x2c, 0xba, + 0xc1, 0x6b, 0x33, 0x74, 0x71, 0xdf, 0xb8, 0x09, 0x9d, 0x63, 0xcd, 0xaa, + 0x75, 0x6a, 0x67, 0xd8, 0x93, 0x93, 0x86, 0x6b, 0x74, 0x12, 0x07, 0x7b, + 0x64, 0xb5, 0x11, 0x8e, 0x3b, 0xe9, 0xf1, 0xdf, 0x61, 0x54, 0x0d, 0xfb, + 0x23, 0xbc, 0xf6, 0xc5, 0xce, 0xd1, 0xad, 0x4f, 0x77, 0xb2, 0xc2, 0x74, + 0x2c, 0xfd, 0xee, 0x2e, 0xf1, 0xc1, 0xeb, 0x21, 0xe6, 0xbb, 0x2c, 0x24, + 0x17, 0xc3, 0x28, 0xc5, 0xdb, 0xa3, 0xcf, 0x38, 0xd4, 0x0e, 0x9e, 0xb9, + 0x5c, 0xc0, 0x94, 0x89, 0x40, 0x89, 0x3e, 0xb9, 0xde, 0xc3, 0x23, 0x89, + 0xd0, 0xd1, 0x9e, 0x64, 0x3b, 0xa1, 0xf9, 0x34, 0x4d, 0x62, 0x0d, 0xce, + 0xf1, 0x33, 0x31, 0xb6, 0x52, 0x86, 0x0d, 0x7d, 0x4a, 0x46, 0x64, 0xd8, + 0x0b, 0xe2, 0x38, 0xd8, 0xa1, 0x34, 0x1b, 0x8b, 0xc3, 0x43, 0xcf, 0x77, + 0x84, 0xcb, 0xf0, 0x4a, 0x92, 0x17, 0x19, 0x8f, 0xdc, 0x4d, 0x6c, 0xc2, + 0xb6, 0x9a, 0x1e, 0xee, 0x3c, 0xf7, 0x79, 0x1f, 0x84, 0x71, 0xc1, 0x46, + 0xc1, 0x33, 0x7a, 0x46, 0xdd, 0x77, 0xfd, 0x18, 0x9b, 0xea, 0xd7, 0xda, + 0xca, 0x6c, 0x86, 0x91, 0x65, 0xff, 0xdc, 0x04, 0xa7, 0x98, 0x67, 0xf9, + 0xa5, 0x9c, 0x65, 0x1d, 0xe0, 0x58, 0x32, 0xbd, 0x7b, 0xb4, 0xc3, 0xba, + 0x25, 0x3b, 0xde, 0xce, 0x79, 0xc1, 0xc1, 0xb0, 0xb7, 0xdf, 0x13, 0x4f, + 0xba, 0xdf, 0x3a, 0x3e, 0xcf, 0x47, 0x58, 0x75, 0x30, 0x2c, 0x4e, 0x73, + 0x75, 0xf7, 0xcf, 0x80, 0x33, 0xe2, 0x56, 0x21, 0x78, 0xa3, 0x3c, 0x03, + 0xcf, 0x57, 0x33, 0xa8, 0xe8, 0xcd, 0x88, 0x25, 0xec, 0x71, 0x20, 0xf2, + 0xe5, 0x2b, 0x9a, 0xad, 0xf0, 0x86, 0xce, 0x0b, 0xa4, 0xac, 0x7a, 0x56, + 0x58, 0x55, 0x26, 0xde, 0x4f, 0xce, 0x76, 0x53, 0xe3, 0xeb, 0xc7, 0x3a, + 0xb5, 0xda, 0xd8, 0xf0, 0xb1, 0x17, 0xa1, 0x86, 0x7f, 0xe4, 0x0c, 0x65, + 0xee, 0xd9, 0x5a, 0xd2, 0x33, 0x3f, 0x72, 0xf6, 0xf7, 0x74, 0xf2, 0x2e, + 0x55, 0x68, 0xde, 0x60, 0xdb, 0x26, 0x52, 0xb8, 0x4f, 0xdd, 0xd8, 0xc9, + 0xfd, 0x8a, 0xe4, 0xb4, 0xef, 0xa3, 0x8f, 0xdf, 0x3a, 0xf5, 0x74, 0x4c, + 0xa5, 0x1c, 0x2b, 0xce, 0x57, 0x2c, 0x84, 0xa3, 0x01, 0x27, 0x92, 0x4e, + 0x25, 0xfc, 0x3c, 0x67, 0x97, 0x4c, 0x7a, 0x10, 0x1c, 0x70, 0x20, 0x53, + 0x4b, 0x2e, 0x96, 0xb0, 0x5a, 0xfc, 0xc0, 0xaf, 0xed, 0x22, 0x29, 0xb1, + 0x25, 0xc6, 0xdb, 0x85, 0xaa, 0x8b, 0x22, 0x4b, 0x3a, 0xae, 0xee, 0x16, + 0x07, 0x6f, 0xc9, 0xe9, 0x88, 0x84, 0x71, 0x52, 0x8c, 0x60, 0x0b, 0x0c, + 0xcf, 0x24, 0x4f, 0x04, 0x5f, 0x0a, 0x51, 0x06, 0xa4, 0x29, 0x22, 0xd2, + 0xd2, 0x5d, 0x39, 0x71, 0xea, 0xb6, 0xfe, 0x96, 0x46, 0xa0, 0xb6, 0xec, + 0x8e, 0x36, 0xa1, 0x21, 0x90, 0xdb, 0xad, 0x76, 0xa5, 0xa4, 0x4e, 0x5e, + 0x2c, 0x57, 0x78, 0xaf, 0xc5, 0x51, 0xb7, 0x46, 0x3c, 0xad, 0x7f, 0x17, + 0xf1, 0x74, 0x0f, 0x71, 0x50, 0xf3, 0x98, 0x4c, 0x48, 0xc8, 0x4f, 0xc5, + 0x45, 0xb3, 0x3e, 0x88, 0x26, 0xec, 0x68, 0x9e, 0x18, 0xb2, 0x48, 0xfd, + 0x71, 0x44, 0xbc, 0x83, 0x6e, 0x37, 0x69, 0x46, 0x8e, 0xdd, 0x80, 0xd2, + 0x98, 0x05, 0xe2, 0xa9, 0x3f, 0x9b, 0xd0, 0x22, 0x44, 0xe1, 0xb0, 0x87, + 0x4e, 0x9a, 0x2f, 0x1f, 0x21, 0x56, 0x85, 0xe3, 0x49, 0x91, 0x57, 0xe2, + 0x70, 0x4f, 0xf0, 0xea, 0x23, 0x37, 0xdb, 0xdc, 0x37, 0xf0, 0xe4, 0x08, + 0xd9, 0x7d, 0x74, 0x71, 0x00, 0xf3, 0xac, 0x65, 0x5c, 0x8a, 0x49, 0x1a, + 0x85, 0xb0, 0xf2, 0x72, 0x47, 0xea, 0x42, 0x52, 0x83, 0xc4, 0x4b, 0xde, + 0xf2, 0x77, 0xec, 0x6e, 0x3f, 0x82, 0x4f, 0x0d, 0x06, 0xa1, 0x94, 0x82, + 0xa1, 0xa3, 0xaf, 0x76, 0x15, 0xe6, 0xad, 0xf3, 0xac, 0x53, 0x92, 0xc4, + 0x0b, 0x75, 0xbe, 0xb5, 0x51, 0x52, 0xc3, 0x50, 0xcd, 0xb7, 0x9e, 0xe9, + 0xf3, 0x36, 0x34, 0xf5, 0x53, 0xbb, 0x3f, 0x65, 0xff, 0xee, 0x07, 0x4f, + 0x68, 0xcd, 0xca, 0x03, 0x00, 0x6e, 0xfa, 0x04, 0x4e, 0xc2, 0x0d, 0xdd, + 0xd2, 0x5c, 0x10, 0x1a, 0x78, 0xa1, 0x4b, 0xb3, 0x38, 0xe8, 0x72, 0x7e, + 0x7a, 0x39, 0x04, 0x58, 0xea, 0x57, 0x1a, 0x4b, 0xa3, 0xa0, 0x2c, 0x5b, + 0x01, 0x67, 0x6d, 0xce, 0xf4, 0xcb, 0x2b, 0x39, 0x5f, 0x27, 0xc9, 0xc2, + 0xac, 0x90, 0xb3, 0xc0, 0x49, 0x7f, 0xf8, 0x4f, 0x0a, 0x49, 0x54, 0x97, + 0xea, 0x67, 0x06, 0xb9, 0xf4, 0x1f, 0x73, 0xab, 0x0e, 0x9c, 0xa8, 0x92, + 0x02, 0x02, 0x45, 0x32, 0xa9, 0x70, 0x86, 0x01, 0x12, 0xc8, 0xd8, 0xe0, + 0x3e, 0x0d, 0xa6, 0xac, 0x86, 0x32, 0x75, 0x81, 0xe5, 0xd5, 0x1f, 0x6d, + 0x83, 0x7a, 0x89, 0x30, 0x5b, 0x1a, 0x2b, 0xba, 0x2a, 0x90, 0xaa, 0xcc, + 0x43, 0x25, 0xaa, 0x02, 0x83, 0x42, 0x41, 0x89, 0x4a, 0x84, 0xaa, 0xae, + 0x8f, 0xab, 0x18, 0xa9, 0xba, 0x33, 0xb4, 0xf5, 0xab, 0xca, 0x70, 0x63, + 0x68, 0xeb, 0x17, 0x53, 0xba, 0x2d, 0xb0, 0x43, 0x27, 0xe7, 0x51, 0xe9, + 0x18, 0x9b, 0x6c, 0x0a, 0x6a, 0x1e, 0x06, 0xee, 0x36, 0x59, 0x42, 0xc7, + 0x3f, 0x26, 0x80, 0x1d, 0x2c, 0x3f, 0xa0, 0xf2, 0x43, 0x96, 0xd5, 0x2a, + 0xf1, 0xa7, 0xcc, 0x2d, 0xe3, 0x53, 0x2e, 0xbb, 0x17, 0x01, 0xae, 0x10, + 0xcc, 0x76, 0x0e, 0xac, 0xe2, 0xc3, 0xce, 0x57, 0x72, 0xa9, 0x76, 0x36, + 0xbe, 0x74, 0x77, 0x78, 0xab, 0x48, 0xb7, 0xa2, 0x6c, 0x26, 0x76, 0xab, + 0x59, 0x12, 0x75, 0x27, 0x5b, 0x82, 0x75, 0xdc, 0xf6, 0x97, 0xb4, 0xae, + 0x1f, 0x93, 0xe5, 0x8b, 0xe2, 0xf0, 0xb0, 0xca, 0x6a, 0xc1, 0xd9, 0x05, + 0xd5, 0x94, 0x5d, 0x50, 0x41, 0x99, 0x45, 0xec, 0xc5, 0xd9, 0xd3, 0x19, + 0x46, 0xe9, 0x45, 0xb8, 0x4b, 0x72, 0xff, 0x87, 0xe2, 0x47, 0x52, 0x8c, + 0xee, 0x9a, 0x95, 0xa3, 0x2b, 0x93, 0x86, 0x78, 0x53, 0x5c, 0x6d, 0x0f, + 0x6b, 0x76, 0x47, 0x47, 0xaf, 0xcb, 0xd6, 0xe8, 0x89, 0xd5, 0x05, 0xe0, + 0x3d, 0xc9, 0xf9, 0x86, 0xcc, 0x6c, 0x3f, 0x39, 0xc5, 0x1b, 0xe4, 0x8b, + 0xf5, 0xd3, 0xe6, 0xf7, 0x70, 0xb7, 0xbe, 0xb7, 0xc1, 0x8e, 0x33, 0x42, + 0x27, 0x7e, 0x10, 0xa3, 0x03, 0x49, 0x98, 0xaf, 0x0e, 0x21, 0x76, 0x4a, + 0xf1, 0xf6, 0x15, 0x5a, 0x5d, 0xf6, 0x52, 0xab, 0x4d, 0x75, 0x67, 0x77, + 0x4e, 0xf8, 0x8a, 0xa7, 0x10, 0x15, 0x4d, 0xb4, 0x51, 0x9d, 0x6d, 0x9f, + 0xf8, 0x22, 0xf5, 0x12, 0x6e, 0x2e, 0xc1, 0x35, 0x9c, 0xa4, 0x1f, 0xc9, + 0x61, 0xf8, 0xb0, 0x27, 0xb7, 0xa8, 0xd8, 0xc5, 0xa6, 0x37, 0xa9, 0x60, + 0x3a, 0x31, 0xdf, 0x6d, 0x26, 0x30, 0x75, 0xd7, 0x9d, 0xc2, 0x64, 0x80, + 0x83, 0x34, 0x33, 0x8a, 0x6f, 0xd6, 0x87, 0x65, 0xa0, 0x10, 0xb9, 0xaf, + 0x6e, 0x76, 0xf3, 0xca, 0x22, 0xe1, 0x88, 0x85, 0x38, 0x4b, 0x21, 0x51, + 0x2a, 0x84, 0xe9, 0xcd, 0xaa, 0xec, 0xe7, 0x41, 0x8c, 0xcf, 0x80, 0x59, + 0x27, 0x91, 0x74, 0x10, 0x14, 0x18, 0xb7, 0xaa, 0x32, 0xd6, 0xe8, 0xdb, + 0x6a, 0xbf, 0x91, 0xc2, 0xe5, 0x5e, 0x0d, 0xd4, 0x2d, 0xf4, 0xac, 0xd6, + 0x37, 0xdf, 0x1b, 0xde, 0x60, 0x0d, 0x1a, 0x28, 0xa5, 0xd8, 0x5f, 0x25, + 0xbd, 0xdb, 0xc5, 0x39, 0x19, 0x74, 0x61, 0xa8, 0x7b, 0xfb, 0xec, 0x18, + 0xe6, 0x1a, 0xfd, 0xdb, 0x9d, 0x37, 0xd2, 0x7f, 0xb1, 0x67, 0x03, 0x1b, + 0x68, 0x40, 0xcb, 0xf0, 0x97, 0x53, 0xb6, 0x39, 0x01, 0x1b, 0x15, 0x57, + 0x86, 0x7a, 0xaf, 0x2a, 0x09, 0x4f, 0x94, 0x53, 0x85, 0x8b, 0x2d, 0x7a, + 0xaf, 0x44, 0x19, 0x3b, 0xcf, 0x3f, 0x44, 0x7c, 0x8b, 0xee, 0x00, 0xae, + 0x52, 0xa9, 0x8e, 0x19, 0x1e, 0xee, 0x1a, 0x50, 0x65, 0xe5, 0x55, 0x7c, + 0x37, 0xb9, 0xc6, 0x23, 0x12, 0x2f, 0x50, 0x39, 0xb3, 0xa3, 0x6c, 0xae, + 0x8c, 0x21, 0x64, 0x67, 0x82, 0x52, 0x7e, 0x39, 0xa5, 0xcf, 0x87, 0x7f, + 0xfb, 0xe9, 0x17, 0xe1, 0x19, 0x71, 0xe3, 0x67, 0x72, 0x07, 0x40, 0x08, + 0x5d, 0xff, 0xb0, 0xcb, 0xba, 0xdd, 0xed, 0x1d, 0xfa, 0x9c, 0x32, 0xad, + 0x0b, 0xd8, 0x87, 0xee, 0xc6, 0x7b, 0xc1, 0xb3, 0x6b, 0x0c, 0x16, 0xfd, + 0xf1, 0xf5, 0xa4, 0x3b, 0x1d, 0x2e, 0x2e, 0x6e, 0x6f, 0xfa, 0xa9, 0x22, + 0xa5, 0x42, 0xe0, 0xe1, 0xdd, 0x70, 0x5a, 0x3c, 0x42, 0xc8, 0x27, 0xa9, + 0xe1, 0x6c, 0x06, 0x14, 0x7c, 0x8a, 0x24, 0xc3, 0xff, 0xbd, 0xed, 0x8e, + 0x80, 0xd3, 0x80, 0xcc, 0x46, 0x22, 0x6a, 0x80, 0x44, 0x97, 0xd3, 0x61, + 0x77, 0x2e, 0x8c, 0xa8, 0x09, 0x52, 0xdd, 0x8c, 0xe7, 0x32, 0xb3, 0x16, + 0xcc, 0x4c, 0x26, 0x6a, 0x83, 0x44, 0xdd, 0xd1, 0xe7, 0xee, 0x57, 0x3e, + 0xbf, 0xf4, 0x99, 0xf2, 0x29, 0x11, 0x71, 0x41, 0xd8, 0xbd, 0x2d, 0x3e, + 0x12, 0x65, 0x37, 0x6e, 0xa2, 0xa0, 0x7b, 0xa3, 0xe1, 0xcd, 0x60, 0x71, + 0xd1, 0xed, 0xcf, 0xc7, 0x53, 0x48, 0xd0, 0xf7, 0xc3, 0xe9, 0x58, 0x23, + 0xe7, 0xf1, 0xcd, 0x50, 0x23, 0xe6, 0xd9, 0xb4, 0x8f, 0x35, 0x3a, 0x1a, + 0x4f, 0x35, 0xa2, 0xbe, 0xba, 0xb9, 0x5b, 0x14, 0x69, 0x61, 0x89, 0x0f, + 0x66, 0xf3, 0x1c, 0x1d, 0x2c, 0x73, 0xc2, 0xb3, 0x48, 0x0b, 0x0b, 0x9e, + 0xf4, 0xdd, 0x1d, 0x4d, 0x3e, 0x75, 0x35, 0xb2, 0x4f, 0xc7, 0x29, 0xd3, + 0x9e, 0x29, 0xc7, 0x29, 0xd3, 0x75, 0x4a, 0xc7, 0x29, 0xd3, 0x9e, 0x83, + 0xb4, 0xfd, 0xf1, 0x4d, 0x61, 0x46, 0x16, 0xac, 0x1c, 0xc2, 0x16, 0x24, + 0x87, 0x35, 0xc5, 0x48, 0xe5, 0x31, 0x58, 0x6a, 0x65, 0x81, 0xe4, 0xb0, + 0xbe, 0x32, 0x79, 0x2d, 0x66, 0xdd, 0xf9, 0xed, 0x14, 0xaf, 0x16, 0xde, + 0xa2, 0x69, 0x60, 0xbc, 0x2c, 0xc1, 0x51, 0x34, 0xdd, 0xeb, 0xf1, 0x60, + 0x08, 0x19, 0x6e, 0x77, 0x30, 0xd0, 0xd8, 0xed, 0xec, 0xb6, 0xa7, 0xb1, + 0xdb, 0xa9, 0x48, 0x02, 0x4b, 0xe1, 0xfa, 0xea, 0x46, 0x63, 0xa8, 0xd7, + 0xdd, 0x2f, 0x1a, 0x13, 0xbd, 0xbe, 0xd5, 0x79, 0x84, 0x59, 0x7f, 0x3a, + 0x1c, 0xde, 0x68, 0xac, 0x72, 0xd0, 0x9d, 0xfe, 0x53, 0x20, 0x82, 0xcd, + 0x71, 0x74, 0x75, 0xf9, 0x69, 0x2e, 0x50, 0x75, 0x4a, 0x45, 0x9f, 0xbe, + 0x50, 0x1a, 0xef, 0x65, 0xd1, 0xcf, 0x30, 0x8b, 0xfe, 0xd5, 0x68, 0x31, + 0x9e, 0x1c, 0xe9, 0x33, 0xfe, 0x39, 0x1c, 0x4e, 0x74, 0xc2, 0x1f, 0x4e, + 0x46, 0xdd, 0xfe, 0x50, 0xeb, 0x32, 0xfa, 0x5a, 0x4f, 0x31, 0xec, 0x1b, + 0x38, 0x89, 0xe1, 0x74, 0xae, 0x51, 0x02, 0xee, 0xea, 0xf3, 0xb4, 0x3b, + 0xd1, 0x69, 0x61, 0x28, 0x53, 0x95, 0x3b, 0x66, 0xa1, 0x1a, 0x48, 0x94, + 0xef, 0x64, 0x7a, 0x75, 0x0d, 0x49, 0x76, 0x32, 0xbe, 0xba, 0x99, 0xcf, + 0x34, 0xb2, 0x1d, 0x5d, 0xdd, 0x0c, 0x75, 0x1b, 0x1f, 0xa1, 0x59, 0x8c, + 0xc6, 0xe3, 0x89, 0x46, 0xbc, 0x94, 0x6e, 0x36, 0x9f, 0x5e, 0x4d, 0x34, + 0x42, 0xc6, 0x24, 0xdd, 0x9b, 0xcb, 0x91, 0xd0, 0x31, 0x2c, 0xe9, 0x94, + 0x2e, 0xc7, 0x14, 0x96, 0x78, 0x46, 0x7c, 0xd1, 0xd5, 0x19, 0x3f, 0x93, + 0xcc, 0x62, 0x7e, 0xc1, 0x27, 0x0e, 0x13, 0x52, 0xe9, 0x48, 0x74, 0xaa, + 0x85, 0x92, 0x48, 0x48, 0xa2, 0x85, 0x7d, 0x37, 0x97, 0x92, 0x44, 0x0c, + 0x3b, 0xef, 0x4c, 0x52, 0x22, 0xad, 0x0d, 0xab, 0x52, 0x96, 0x96, 0xd4, + 0x00, 0xd6, 0xab, 0x28, 0x31, 0x89, 0xdc, 0x2e, 0x9a, 0x61, 0x92, 0xa2, + 0x4a, 0x81, 0x5c, 0xd2, 0x8c, 0x22, 0x41, 0x77, 0x61, 0xb4, 0x12, 0x81, + 0x95, 0x12, 0x10, 0x74, 0x17, 0xe0, 0xef, 0xcd, 0xf4, 0xef, 0x0c, 0xdd, + 0x05, 0xa0, 0x68, 0x49, 0x14, 0x02, 0xac, 0x0b, 0x40, 0xdb, 0xfe, 0x90, + 0x79, 0x20, 0x27, 0x8f, 0xe7, 0x02, 0x90, 0x9f, 0xa5, 0xe4, 0x10, 0x90, + 0x0b, 0x40, 0xdf, 0x49, 0xe9, 0x8b, 0x40, 0x2e, 0x00, 0xf5, 0xb9, 0x44, + 0x8d, 0xcf, 0x2d, 0x64, 0xad, 0x3e, 0x79, 0x01, 0x0e, 0xfd, 0xe9, 0x5b, + 0x53, 0x50, 0x5c, 0x99, 0x40, 0x93, 0x64, 0xd3, 0x7d, 0x2d, 0xf0, 0xb7, + 0xaf, 0x28, 0xcb, 0x4d, 0x83, 0x10, 0x26, 0x69, 0x86, 0x33, 0x6d, 0x9b, + 0xbd, 0x15, 0xad, 0xd0, 0xd8, 0xe6, 0x1d, 0xaf, 0xc9, 0x49, 0x25, 0xdf, + 0x96, 0xa4, 0xd1, 0xd4, 0xc3, 0x6e, 0xe4, 0x5a, 0xf3, 0x2e, 0x4f, 0x01, + 0xab, 0xb1, 0x9a, 0x05, 0xd1, 0xc4, 0xa1, 0xe3, 0x47, 0xe4, 0x6c, 0x87, + 0x36, 0xae, 0xbb, 0x5e, 0x62, 0xea, 0x92, 0x1c, 0x27, 0xbb, 0xd7, 0x5e, + 0x05, 0x07, 0x1f, 0x38, 0x6a, 0x98, 0xe6, 0x58, 0x93, 0xa1, 0x64, 0xe6, + 0xc5, 0x01, 0x70, 0x1c, 0x72, 0x5f, 0xbc, 0x7a, 0x74, 0x3c, 0x9f, 0x54, + 0xda, 0xa7, 0x88, 0x34, 0xc0, 0x38, 0x0c, 0x6e, 0x05, 0xf5, 0x69, 0xeb, + 0x0c, 0xde, 0x47, 0x1a, 0xc7, 0xf7, 0xee, 0xee, 0xac, 0x38, 0xed, 0xd9, + 0x0f, 0x9a, 0x69, 0xb6, 0x8a, 0x40, 0xe0, 0x1f, 0xc8, 0xba, 0xce, 0x65, + 0x17, 0x70, 0xd7, 0x1f, 0xa0, 0x95, 0xb3, 0x7a, 0x74, 0x41, 0xe3, 0xb2, + 0xeb, 0xb2, 0x13, 0x10, 0xde, 0x2b, 0xd2, 0x57, 0xe2, 0xde, 0x8a, 0xf9, + 0x85, 0x91, 0x62, 0xaa, 0x74, 0x5e, 0xc6, 0x13, 0xcd, 0x35, 0xc6, 0x66, + 0x5f, 0x9a, 0x78, 0x37, 0x15, 0x92, 0x6d, 0x15, 0xf5, 0x73, 0xb5, 0xdb, + 0x6f, 0xbd, 0x95, 0x17, 0x97, 0x0f, 0x9f, 0x3e, 0x60, 0x27, 0x92, 0xa4, + 0x89, 0x16, 0xff, 0x1b, 0x2f, 0x22, 0x92, 0xd1, 0xd8, 0xc5, 0xd1, 0x0c, + 0x5f, 0x92, 0xd1, 0xcc, 0x0e, 0x7b, 0x37, 0x24, 0xbd, 0x82, 0x99, 0x93, + 0x25, 0x85, 0xcd, 0x91, 0x1e, 0xda, 0xbb, 0x69, 0xcb, 0x28, 0x6d, 0x99, + 0xb8, 0x0b, 0xb4, 0x85, 0xdf, 0x91, 0xda, 0x46, 0x38, 0x39, 0x00, 0x5b, + 0xd5, 0xec, 0x0d, 0x2a, 0x1f, 0xc3, 0xe0, 0x59, 0xd9, 0x5c, 0x7f, 0x17, + 0xb4, 0x62, 0xd7, 0x40, 0x6f, 0x24, 0xfd, 0xcc, 0xb9, 0x66, 0xa2, 0x96, + 0x2e, 0xb8, 0x4a, 0x47, 0x4f, 0x6f, 0x3f, 0xd2, 0x66, 0x40, 0x7a, 0xb1, + 0xe2, 0x5c, 0x74, 0xec, 0x2a, 0xce, 0xac, 0xc9, 0x97, 0x2a, 0x87, 0xdf, + 0x9a, 0x19, 0x00, 0x7a, 0x01, 0x60, 0x5b, 0x1c, 0x8a, 0xeb, 0x08, 0x96, + 0xe8, 0xc4, 0x4d, 0x9e, 0x56, 0x7d, 0x2c, 0xab, 0xba, 0xd0, 0x62, 0x4d, + 0x55, 0x11, 0x6c, 0xba, 0xc3, 0xab, 0xd0, 0xaa, 0x0c, 0xde, 0xeb, 0x30, + 0x0e, 0xe9, 0x71, 0x4b, 0xc1, 0x47, 0xfd, 0x34, 0x84, 0x5c, 0x4a, 0xb7, + 0xd0, 0xc1, 0xa7, 0x89, 0x6e, 0xb8, 0x84, 0x5b, 0x98, 0xf1, 0x21, 0x05, + 0x89, 0x38, 0x89, 0x3e, 0x72, 0xec, 0x1c, 0x45, 0xa7, 0xe6, 0x90, 0x3c, + 0x2a, 0xc4, 0x1f, 0x05, 0x63, 0x73, 0xb4, 0xb2, 0x7b, 0x53, 0x96, 0xe6, + 0xb0, 0x65, 0x1b, 0x82, 0x1e, 0x15, 0xec, 0x49, 0xdd, 0xe5, 0xc1, 0xc7, + 0xce, 0x0a, 0xef, 0x25, 0x94, 0x27, 0x0a, 0x0e, 0xb4, 0xaa, 0x75, 0x27, + 0xdc, 0xd0, 0x2b, 0xca, 0x1c, 0xb5, 0x7d, 0x99, 0x20, 0x54, 0x99, 0x3e, + 0xf9, 0xc8, 0x00, 0xe5, 0xb2, 0x1d, 0x77, 0x9b, 0x21, 0xa7, 0x24, 0x2a, + 0x95, 0x97, 0x94, 0xde, 0x04, 0x7a, 0x45, 0x9c, 0x90, 0xa3, 0x8c, 0x1e, + 0x06, 0x1a, 0xa9, 0x6c, 0xf3, 0x30, 0x1b, 0xc0, 0xe4, 0xcb, 0xe4, 0x73, + 0x96, 0x8b, 0x5e, 0xa9, 0x7c, 0xae, 0x9d, 0xf0, 0x77, 0x8d, 0xaf, 0x39, + 0x97, 0x7d, 0x0d, 0x0c, 0x48, 0xa3, 0x92, 0x6b, 0xd9, 0x35, 0x96, 0xc9, + 0x7e, 0x37, 0xc1, 0x7f, 0xc4, 0xcb, 0xf6, 0x91, 0x95, 0x72, 0xe0, 0x51, + 0x63, 0x1b, 0xdc, 0x13, 0x33, 0xdc, 0x91, 0xf2, 0x28, 0x6c, 0x8c, 0xb7, + 0x57, 0x17, 0x88, 0x56, 0x4d, 0xf2, 0x57, 0x05, 0xc2, 0xeb, 0x39, 0xf8, + 0x79, 0x9b, 0xd8, 0xc1, 0x97, 0xf1, 0x94, 0xf0, 0x00, 0x6c, 0x58, 0x7f, + 0x0f, 0x6f, 0x62, 0xc4, 0xe6, 0x98, 0x37, 0x95, 0xbd, 0x8f, 0x39, 0xf8, + 0x4d, 0x45, 0xef, 0x63, 0x8e, 0x94, 0x66, 0xec, 0x7d, 0xf4, 0x75, 0x3f, + 0x53, 0xe7, 0x59, 0x51, 0xee, 0xa6, 0xf7, 0xb2, 0x0a, 0xf8, 0x94, 0x4a, + 0x0f, 0xbe, 0x59, 0xb9, 0x22, 0xc2, 0xf4, 0x0f, 0xd8, 0xf6, 0xf5, 0x50, + 0x36, 0x32, 0xbd, 0xa5, 0x2d, 0xbc, 0x92, 0xe9, 0xed, 0x62, 0x6e, 0xa9, + 0x94, 0xbe, 0xa1, 0x85, 0x1b, 0x90, 0xe0, 0x5f, 0x3a, 0x0a, 0x22, 0x0e, + 0xd7, 0x72, 0xae, 0xa0, 0x98, 0xe5, 0x80, 0x5f, 0x2c, 0xd5, 0xfc, 0xef, + 0xff, 0xab, 0x40, 0x0a, 0x01, 0x87, 0x94, 0x78, 0xa4, 0x46, 0x76, 0x86, + 0x29, 0x41, 0xba, 0x32, 0x74, 0x2c, 0xc2, 0x4b, 0x66, 0xb3, 0x40, 0xfa, + 0x2f, 0xed, 0x58, 0xde, 0x66, 0x2d, 0x8c, 0x84, 0x5d, 0xe3, 0x7d, 0x29, + 0xfc, 0xb5, 0x97, 0x82, 0xcd, 0x93, 0x74, 0x0a, 0xbc, 0x23, 0x55, 0x9a, + 0x28, 0x7d, 0xff, 0xe4, 0x29, 0xc0, 0x8e, 0x4c, 0x2a, 0xdf, 0x93, 0x70, + 0x83, 0xf7, 0x89, 0xcf, 0x10, 0xa4, 0x35, 0xf0, 0x5a, 0x98, 0xbc, 0x59, + 0xd3, 0x96, 0x70, 0x26, 0x6f, 0xba, 0xe4, 0x21, 0x41, 0x55, 0xc7, 0x6f, + 0x8a, 0xbf, 0x54, 0x8a, 0x88, 0x6a, 0x0c, 0x56, 0x53, 0x6c, 0x5b, 0xc4, + 0x60, 0xaa, 0x04, 0x8e, 0xc6, 0x9b, 0x23, 0x33, 0x38, 0x26, 0xa1, 0x81, + 0x0a, 0x99, 0x49, 0xdd, 0x82, 0x21, 0xa6, 0x54, 0x2a, 0xe2, 0x15, 0x63, + 0xf8, 0x56, 0xa9, 0x9f, 0x30, 0x34, 0xe6, 0x66, 0xde, 0x98, 0xaf, 0x7c, + 0xcc, 0xd4, 0x5f, 0x55, 0x31, 0xeb, 0x2a, 0x26, 0xd9, 0x30, 0xa8, 0x2a, + 0xd6, 0x98, 0xa4, 0xc9, 0x2a, 0x31, 0xb7, 0xc9, 0x33, 0x38, 0x15, 0x96, + 0xe3, 0xc7, 0x0b, 0x66, 0x52, 0xf9, 0x80, 0x85, 0x85, 0x7a, 0xc0, 0x94, + 0xb4, 0x39, 0x7a, 0xb7, 0xf2, 0xa3, 0xad, 0x9c, 0x5f, 0x36, 0xea, 0x0e, + 0x52, 0x8d, 0xec, 0xa0, 0xa9, 0x46, 0xe0, 0x52, 0x59, 0xf5, 0x9f, 0x02, + 0xbf, 0x55, 0x2e, 0x0b, 0x20, 0xad, 0x55, 0x41, 0x16, 0x1d, 0x50, 0x16, + 0xc0, 0x7a, 0x7f, 0x0b, 0xa9, 0x18, 0xec, 0x1b, 0x7f, 0xad, 0x35, 0xf5, + 0x66, 0x72, 0x6e, 0x66, 0xd9, 0xd1, 0x1e, 0x01, 0x74, 0x4d, 0x84, 0x4d, + 0x7f, 0x4e, 0x07, 0x5a, 0x76, 0x93, 0x24, 0xd3, 0x19, 0x94, 0xcc, 0x2b, + 0x78, 0x28, 0x35, 0x53, 0x2d, 0x23, 0xda, 0xca, 0x56, 0x10, 0x0c, 0x42, + 0x06, 0x4c, 0x81, 0x54, 0xb3, 0x4b, 0xce, 0x09, 0x38, 0xad, 0xaa, 0x9d, + 0x13, 0x65, 0x9e, 0x6c, 0x46, 0x06, 0x68, 0x5e, 0x98, 0x38, 0x01, 0x1e, + 0xfb, 0x72, 0xfa, 0xb5, 0x0a, 0x2c, 0x22, 0x07, 0xb7, 0x10, 0x87, 0xaa, + 0x42, 0x0d, 0x50, 0xf7, 0x3e, 0x31, 0x03, 0xb7, 0xa3, 0xb4, 0x23, 0x23, + 0x84, 0x3b, 0x4a, 0x3a, 0x2f, 0x20, 0xd2, 0x41, 0xaf, 0xa8, 0x4a, 0x14, + 0xd7, 0xce, 0x76, 0xf6, 0x3c, 0xb0, 0x98, 0xfe, 0x36, 0x8d, 0xe4, 0x9f, + 0xf2, 0xc9, 0x80, 0xb2, 0xdd, 0xd1, 0xd7, 0x62, 0x77, 0xa9, 0x62, 0x15, + 0x9d, 0xf9, 0x9d, 0x65, 0xb3, 0x98, 0x67, 0xf7, 0xb1, 0x17, 0xc9, 0x7d, + 0x2c, 0x62, 0x71, 0x07, 0x34, 0x1f, 0x3e, 0xa0, 0xc4, 0x38, 0xc6, 0xec, + 0xc4, 0x98, 0x1c, 0xb8, 0xd2, 0xe8, 0x60, 0x13, 0x6c, 0xb7, 0xc1, 0xb3, + 0xf0, 0x72, 0xa2, 0xa1, 0xf6, 0x18, 0x25, 0x7d, 0x24, 0x30, 0x79, 0x49, + 0x1f, 0xf4, 0x25, 0xe9, 0x6c, 0xef, 0xae, 0x00, 0xfe, 0x5c, 0x0c, 0xd0, + 0xa9, 0xb4, 0x4c, 0x0e, 0xb9, 0xa2, 0x03, 0x40, 0x1a, 0xa4, 0xdf, 0x34, + 0x2b, 0x28, 0x15, 0x14, 0x03, 0xb4, 0xf9, 0xa1, 0x82, 0xef, 0x61, 0xa8, + 0x83, 0x9f, 0xb1, 0x87, 0x2a, 0x89, 0x17, 0xbb, 0xa3, 0x66, 0x8a, 0xcf, + 0xab, 0xec, 0x04, 0x6e, 0x74, 0xdd, 0xa2, 0xf4, 0xfa, 0xab, 0xc0, 0x8f, + 0xdc, 0xd5, 0x81, 0xae, 0x41, 0x91, 0x7f, 0xc4, 0x3b, 0x40, 0x4e, 0x94, + 0x6a, 0xf0, 0x89, 0xfd, 0x29, 0x57, 0xa9, 0xdc, 0xac, 0xa0, 0x30, 0xd9, + 0x06, 0x70, 0x1f, 0x2c, 0x53, 0x1e, 0x07, 0xc5, 0x20, 0x0a, 0x82, 0xf2, + 0x2a, 0x29, 0xd9, 0x56, 0x4b, 0x38, 0x4d, 0x7d, 0xbc, 0xc9, 0x0d, 0xb6, + 0xd8, 0xbf, 0x5c, 0x06, 0x22, 0xdc, 0x30, 0xb3, 0xec, 0x21, 0x7b, 0xc1, + 0x0b, 0x75, 0x9b, 0x52, 0xd0, 0x2f, 0xa6, 0x28, 0xe0, 0xe9, 0x0c, 0xde, + 0x65, 0xf5, 0xc8, 0x24, 0x93, 0x5e, 0x8a, 0xf7, 0x17, 0xfa, 0xef, 0x55, + 0x5c, 0x84, 0x81, 0x1f, 0xab, 0x19, 0xe8, 0x53, 0xb1, 0xe9, 0x3c, 0x26, + 0x0e, 0x5e, 0xc8, 0xe3, 0x7d, 0x71, 0x05, 0xdb, 0x99, 0xeb, 0x12, 0xaa, + 0xff, 0xc0, 0x04, 0x29, 0x45, 0xf3, 0x61, 0xe0, 0x6e, 0x4e, 0x52, 0x24, + 0x58, 0x60, 0x66, 0x1b, 0x32, 0x4b, 0xff, 0x5c, 0xce, 0x8e, 0x43, 0x4b, + 0x54, 0x62, 0xa7, 0x86, 0x9e, 0xcb, 0x36, 0xd6, 0x42, 0x39, 0xba, 0x96, + 0xab, 0x02, 0xa1, 0xd0, 0xa0, 0xee, 0x9f, 0x31, 0x99, 0xba, 0x1b, 0xb6, + 0x6e, 0x8d, 0xbc, 0x41, 0x89, 0x8f, 0xeb, 0x64, 0xbe, 0x9e, 0x55, 0xca, + 0xaa, 0x6d, 0xf8, 0xee, 0x52, 0x7e, 0x76, 0x1d, 0x15, 0x57, 0xb0, 0xad, + 0x9f, 0x40, 0x9a, 0xc4, 0xa7, 0x9d, 0xad, 0xb1, 0x24, 0x36, 0x12, 0x92, + 0x93, 0x90, 0xa5, 0xcc, 0xe6, 0x21, 0xd5, 0x9f, 0x6b, 0x79, 0x46, 0xe1, + 0x4a, 0xc9, 0x93, 0x6b, 0xac, 0x1a, 0x4f, 0x18, 0x84, 0x97, 0xfb, 0x2b, + 0xa1, 0xc8, 0x18, 0x3c, 0x17, 0x6f, 0xf7, 0x8f, 0x8e, 0xc1, 0x94, 0x3b, + 0xc6, 0xa3, 0x13, 0x39, 0x96, 0x4d, 0xb8, 0x79, 0x14, 0x47, 0x0d, 0xe6, + 0x70, 0x7e, 0xb6, 0x65, 0xd6, 0xd5, 0x2e, 0x58, 0x17, 0x09, 0xb2, 0xe3, + 0xe4, 0x2e, 0x07, 0xcc, 0x5b, 0xd3, 0x81, 0x9c, 0x5c, 0x58, 0xed, 0x23, + 0x1f, 0x24, 0xf7, 0xc8, 0x6e, 0xa9, 0x6a, 0x6f, 0xe0, 0x64, 0x2f, 0x43, + 0xd7, 0xf5, 0x95, 0x0c, 0x0c, 0x8a, 0x46, 0xa6, 0x04, 0x24, 0x4d, 0xd1, + 0xbc, 0xe2, 0xe2, 0xcc, 0xae, 0x24, 0x13, 0x73, 0xe4, 0xfb, 0x07, 0xb8, + 0xbb, 0x4d, 0xdd, 0xc8, 0x0d, 0x9f, 0x84, 0x37, 0xb3, 0x15, 0xc7, 0x4d, + 0xb3, 0xc8, 0xf3, 0x24, 0x8b, 0x8c, 0x08, 0xd4, 0xd1, 0x8a, 0xf5, 0xbb, + 0xc2, 0x0e, 0x2e, 0xf0, 0x49, 0x65, 0x24, 0xdb, 0xbe, 0x77, 0x74, 0x04, + 0x25, 0x2b, 0xc2, 0xb0, 0x13, 0xfb, 0x88, 0x4e, 0xf4, 0x16, 0x20, 0xf7, + 0x61, 0x1d, 0xd1, 0x87, 0x3e, 0xd7, 0x25, 0xf7, 0x51, 0x3f, 0xa2, 0x8f, + 0x6a, 0xa6, 0x70, 0xde, 0xe6, 0xa6, 0x50, 0x40, 0x86, 0x05, 0x2f, 0x20, + 0x09, 0xd8, 0x46, 0x63, 0x80, 0x26, 0x61, 0xf0, 0x14, 0xfc, 0x4e, 0x4a, + 0x37, 0xe5, 0xc3, 0xa9, 0xb0, 0xef, 0x9b, 0x7c, 0x2c, 0x2c, 0xe1, 0xf6, + 0x0f, 0x7a, 0xf2, 0xaa, 0x11, 0xdc, 0xe3, 0x7f, 0x28, 0x6a, 0x1b, 0x6c, + 0xfd, 0xf5, 0x0d, 0x73, 0x06, 0x4a, 0x68, 0x58, 0x7d, 0x20, 0x93, 0x6e, + 0x83, 0x4a, 0x16, 0xfa, 0x50, 0xe6, 0x1d, 0x30, 0xd7, 0x28, 0x6a, 0xc9, + 0x34, 0xff, 0x19, 0xff, 0x40, 0x2b, 0x7f, 0x11, 0x47, 0x57, 0x57, 0x61, + 0x78, 0x69, 0x47, 0x9a, 0x05, 0x12, 0x09, 0x34, 0x0c, 0x0c, 0x40, 0x72, + 0x6e, 0x10, 0x4d, 0xbc, 0x29, 0xc6, 0xee, 0x1f, 0x95, 0x30, 0x76, 0xd5, + 0x99, 0x47, 0x82, 0x1f, 0x9a, 0xb2, 0x74, 0x44, 0x35, 0xa8, 0xbe, 0xb5, + 0x52, 0x72, 0xe7, 0xf4, 0x8e, 0x71, 0x7b, 0x6c, 0xc1, 0xd3, 0x79, 0xb6, + 0x7b, 0xde, 0xbb, 0x61, 0x40, 0x9f, 0x0c, 0x14, 0x60, 0x6f, 0xa1, 0x82, + 0x9e, 0xf3, 0x0e, 0x3f, 0xf6, 0xe7, 0xc8, 0xa1, 0x33, 0x55, 0x8e, 0x86, + 0xd6, 0xb1, 0x3f, 0x25, 0xc0, 0x0a, 0xe8, 0xae, 0xfe, 0x9f, 0xf4, 0xe6, + 0x3d, 0x7f, 0x07, 0xaf, 0xdf, 0xc4, 0xba, 0x0c, 0x2a, 0x89, 0x70, 0x2b, + 0x74, 0x81, 0xcf, 0xf1, 0x8f, 0xde, 0xc3, 0x23, 0xb6, 0x56, 0x96, 0x0f, + 0x21, 0xa0, 0x16, 0x39, 0x28, 0x87, 0x2a, 0xf6, 0xaa, 0xe9, 0x6a, 0x1b, + 0x3c, 0x9b, 0xf5, 0xa4, 0xb7, 0xe9, 0x04, 0x70, 0x22, 0x79, 0x20, 0x8c, + 0xa5, 0xf3, 0xad, 0xdb, 0x22, 0xbd, 0x96, 0x4a, 0x52, 0xa5, 0x1c, 0x51, + 0x18, 0x2a, 0x67, 0x78, 0x13, 0x1c, 0x61, 0x01, 0xeb, 0x52, 0x58, 0xea, + 0x0c, 0x2a, 0x58, 0xe5, 0x08, 0xde, 0x08, 0x48, 0x18, 0xc6, 0xf0, 0xcd, + 0xb0, 0xe0, 0xdf, 0x31, 0x7c, 0x25, 0x0c, 0x5f, 0x10, 0xc6, 0xfa, 0x1d, + 0xc3, 0xf7, 0x4f, 0xc1, 0xf0, 0x05, 0x71, 0xbd, 0x4d, 0x30, 0x7c, 0xc1, + 0x1b, 0x98, 0xc8, 0x6e, 0xfe, 0xdc, 0x81, 0x9d, 0x8b, 0x01, 0x86, 0x2f, + 0xb4, 0xfe, 0x04, 0x8e, 0x46, 0xe0, 0xaf, 0x3b, 0xcf, 0x3f, 0x2d, 0xc5, + 0xf1, 0x05, 0x41, 0xc5, 0xff, 0x2e, 0x38, 0xbe, 0xa4, 0xfa, 0xea, 0x08, + 0x1c, 0x5f, 0xbb, 0xf5, 0x3d, 0x81, 0x7c, 0xb5, 0xdc, 0xdf, 0x1e, 0xc9, + 0x97, 0x44, 0xb1, 0xff, 0x0f, 0x90, 0x7c, 0xd3, 0x77, 0x7d, 0x59, 0xb2, + 0x5a, 0x03, 0xea, 0x8b, 0x4e, 0x26, 0xb8, 0x03, 0xeb, 0xe3, 0xb7, 0xc3, + 0x4d, 0xb6, 0xdf, 0x0c, 0xe3, 0xb4, 0x6d, 0x80, 0xa8, 0x95, 0x2e, 0xaf, + 0xde, 0x64, 0x42, 0x37, 0x34, 0x1c, 0xec, 0x85, 0x62, 0x55, 0x1c, 0x14, + 0x18, 0x55, 0xae, 0xf4, 0xdb, 0x25, 0x9d, 0x34, 0xec, 0xe5, 0x7e, 0x5f, + 0xb1, 0xea, 0x2f, 0x6d, 0xdb, 0x6e, 0x8a, 0x6d, 0xcd, 0x2a, 0x00, 0xd3, + 0xb6, 0x96, 0xdd, 0x11, 0x1b, 0x9b, 0x54, 0x75, 0xf0, 0x9b, 0x1f, 0x29, + 0x63, 0x01, 0xe4, 0x23, 0x5a, 0xfa, 0x4d, 0x44, 0x89, 0x23, 0x6b, 0x09, + 0x41, 0xe0, 0xf1, 0x38, 0xb2, 0x16, 0xb4, 0x62, 0xaa, 0x02, 0xc9, 0xd2, + 0x7b, 0xf8, 0x6a, 0x48, 0x82, 0x45, 0xd6, 0xf4, 0x75, 0x95, 0xc3, 0xf1, + 0x5f, 0x39, 0xec, 0xb0, 0x2e, 0xea, 0x05, 0xb5, 0xa9, 0x66, 0x47, 0xcc, + 0x41, 0x6b, 0x48, 0x25, 0xcd, 0x2d, 0x0a, 0xb3, 0xa4, 0x31, 0xa6, 0x92, + 0xf6, 0xd8, 0xb1, 0x2e, 0x4b, 0x2f, 0xbb, 0x35, 0x82, 0x49, 0xf0, 0x94, + 0x4b, 0x05, 0x64, 0x57, 0x17, 0x50, 0x91, 0xed, 0x51, 0x82, 0x02, 0xd8, + 0x1c, 0x25, 0x30, 0x80, 0x4f, 0x55, 0xc1, 0x39, 0x22, 0xfa, 0x34, 0x6e, + 0x4f, 0xbb, 0x88, 0xa8, 0xf1, 0xd2, 0xd2, 0x0d, 0x47, 0x81, 0x3e, 0x2d, + 0x79, 0x3e, 0xb4, 0x76, 0x37, 0x0e, 0xf6, 0x99, 0x62, 0xad, 0x85, 0xd8, + 0x09, 0x79, 0x3e, 0xeb, 0x95, 0x21, 0x26, 0x52, 0x0d, 0x70, 0x2e, 0xf5, + 0x37, 0xdf, 0x38, 0xec, 0x8f, 0x25, 0xbb, 0x66, 0x1e, 0x55, 0x59, 0x0b, + 0xfb, 0xa9, 0x78, 0x31, 0x6b, 0xc6, 0x56, 0x77, 0xd6, 0x53, 0x3b, 0x96, + 0xaa, 0x62, 0xb4, 0x0c, 0xc4, 0x68, 0x49, 0x62, 0x2c, 0x83, 0x7e, 0x46, + 0x27, 0xfd, 0x60, 0xb7, 0xc3, 0xff, 0x96, 0x7e, 0x6b, 0xf2, 0x20, 0x51, + 0xce, 0x49, 0xd3, 0x97, 0x1e, 0xc0, 0xe3, 0x4c, 0x03, 0x3f, 0x9f, 0x3d, + 0xcf, 0x92, 0x5e, 0x8b, 0x08, 0x8f, 0x55, 0x0c, 0xb0, 0x9f, 0xe5, 0x07, + 0x5a, 0x2a, 0x46, 0x85, 0x72, 0x7d, 0x45, 0x76, 0xb5, 0x76, 0xaf, 0x46, + 0xa2, 0x6e, 0x1a, 0x7c, 0x96, 0x3a, 0x65, 0x42, 0x93, 0xa3, 0x24, 0xda, + 0xcb, 0x63, 0x52, 0x03, 0x6c, 0x0d, 0x90, 0xf1, 0xf9, 0xd8, 0x52, 0x68, + 0xeb, 0xd1, 0xfc, 0x74, 0x34, 0xd4, 0x3a, 0xaa, 0x62, 0xbb, 0x04, 0x12, + 0x5b, 0x59, 0x4a, 0x05, 0xe4, 0xc0, 0x8d, 0xa0, 0xb0, 0x9b, 0x05, 0x09, + 0x7f, 0x63, 0x58, 0xd7, 0x7c, 0xb3, 0xb0, 0xae, 0xf9, 0x7d, 0xc2, 0xba, + 0xe6, 0xbf, 0x43, 0x58, 0x77, 0x45, 0x5f, 0xe1, 0xe8, 0x01, 0x9c, 0x6d, + 0x7d, 0x34, 0xc6, 0x58, 0x69, 0x61, 0x9c, 0xf5, 0xc9, 0x10, 0x55, 0xa8, + 0x89, 0xae, 0x55, 0xe5, 0x43, 0x85, 0xc1, 0xe9, 0x7c, 0xb1, 0x2a, 0x4d, + 0x58, 0x6d, 0x4b, 0xab, 0xe2, 0x8b, 0x65, 0x9f, 0xca, 0x20, 0xc1, 0xcb, + 0x7c, 0x71, 0xc5, 0xcd, 0x0c, 0x48, 0x54, 0x42, 0x6f, 0x92, 0x8a, 0x85, + 0x15, 0x50, 0x22, 0xda, 0xdb, 0xa3, 0xaf, 0x40, 0x6a, 0xbf, 0x70, 0x81, + 0x05, 0x2c, 0x33, 0x08, 0xc3, 0xbe, 0xa1, 0xb2, 0xa2, 0x0c, 0x6d, 0x4a, + 0x6e, 0x06, 0x5b, 0xbc, 0x19, 0xb4, 0x3d, 0xc9, 0x94, 0x3a, 0x0c, 0x3f, + 0x42, 0xb7, 0x86, 0x6e, 0x7b, 0xb5, 0x2d, 0xa5, 0x46, 0x27, 0x16, 0x7f, + 0x84, 0x46, 0xd2, 0xac, 0xee, 0x47, 0xed, 0x4b, 0x29, 0xa1, 0xb1, 0x2d, + 0xbc, 0x60, 0xcb, 0xb5, 0x56, 0xbd, 0x9b, 0x22, 0x0d, 0x4e, 0x6e, 0x02, + 0xf4, 0x65, 0x3c, 0xe5, 0xc4, 0xcd, 0x32, 0x62, 0x89, 0xb2, 0x65, 0xb0, + 0xb0, 0xbb, 0x02, 0xc6, 0x7d, 0x41, 0x93, 0x7a, 0xd7, 0xdb, 0xbb, 0x9c, + 0x96, 0x31, 0x30, 0xf0, 0xb8, 0x63, 0xf1, 0x99, 0xdf, 0x46, 0x32, 0x08, + 0x65, 0xc2, 0x31, 0x33, 0x88, 0xa4, 0x31, 0x73, 0x29, 0x65, 0x66, 0x11, + 0x85, 0x0f, 0xcb, 0xce, 0xc2, 0x21, 0xb5, 0x1e, 0x1d, 0xad, 0x71, 0x10, + 0x62, 0x3d, 0x6e, 0xff, 0xc3, 0xd2, 0xaa, 0x2f, 0x1c, 0xfb, 0xe0, 0x69, + 0x8d, 0x20, 0x25, 0xd5, 0xea, 0xdb, 0x59, 0x3e, 0x84, 0x56, 0x8b, 0x44, + 0x3b, 0x1a, 0x5d, 0xd3, 0x89, 0xd4, 0xc8, 0x45, 0xbf, 0xbb, 0x46, 0x85, + 0x56, 0xaa, 0xcf, 0x54, 0x13, 0xc2, 0x66, 0xb3, 0xc9, 0x3f, 0x92, 0xd3, + 0x56, 0x10, 0xb2, 0x4f, 0x10, 0x14, 0xc1, 0xf9, 0xf2, 0xf3, 0xb2, 0xac, + 0xcd, 0xe2, 0x81, 0xfc, 0x03, 0xcf, 0x6f, 0xa3, 0x7d, 0xe0, 0x47, 0x3e, + 0x89, 0xd0, 0xb0, 0x31, 0x9d, 0xee, 0x9d, 0x5f, 0xf8, 0xc0, 0xc8, 0x32, + 0x42, 0xe5, 0x43, 0xbf, 0x30, 0x25, 0x2c, 0xbe, 0xf3, 0x03, 0x3b, 0xf7, + 0x78, 0xe7, 0x96, 0x5a, 0x5b, 0x8c, 0x8e, 0x53, 0xaa, 0xd4, 0x15, 0xa6, + 0x84, 0x79, 0x6c, 0x48, 0x45, 0xef, 0x82, 0xa9, 0x58, 0x2a, 0x1d, 0x91, + 0xde, 0x0f, 0x94, 0x6b, 0x4a, 0xa9, 0x52, 0x52, 0x98, 0x12, 0x16, 0xb1, + 0xe1, 0x80, 0xde, 0xad, 0xb6, 0x20, 0x78, 0x4b, 0xad, 0x22, 0x46, 0xc7, + 0x29, 0x95, 0x3a, 0x4a, 0x09, 0x8b, 0xa0, 0x70, 0x60, 0xef, 0x82, 0xe4, + 0x6d, 0xb5, 0x8e, 0x18, 0x1d, 0xa7, 0x54, 0xea, 0x28, 0x25, 0xcc, 0x28, + 0x95, 0x3a, 0xa2, 0xbd, 0x8b, 0x8b, 0x54, 0xad, 0x23, 0x46, 0xc7, 0x79, + 0x2a, 0x75, 0x94, 0x12, 0x66, 0x94, 0x4a, 0x1d, 0x91, 0xaf, 0x80, 0x48, + 0x94, 0x25, 0x3a, 0xea, 0xc8, 0x33, 0x52, 0xeb, 0x28, 0x21, 0xcc, 0x28, + 0x95, 0x3a, 0x4a, 0x09, 0x33, 0xbf, 0x53, 0xa6, 0xa3, 0x8e, 0x38, 0xf7, + 0x86, 0x5a, 0x47, 0x1d, 0x59, 0xf2, 0x0d, 0xa5, 0x8e, 0x52, 0xc2, 0x8c, + 0xb2, 0x4c, 0x47, 0x9d, 0x83, 0x60, 0x21, 0x0d, 0xb5, 0x8e, 0x3a, 0xb2, + 0xe4, 0x1b, 0x4a, 0x1d, 0xa5, 0x84, 0x19, 0xa5, 0x4a, 0x47, 0xc4, 0xdb, + 0xbf, 0x74, 0xc4, 0xb9, 0x97, 0xe8, 0xe8, 0x45, 0xd2, 0x66, 0x83, 0x5f, + 0x0c, 0xa9, 0x77, 0xd8, 0xec, 0xab, 0x37, 0x3b, 0xb0, 0xbc, 0xc3, 0x32, + 0x08, 0x4a, 0xaf, 0x7c, 0x1c, 0xd3, 0xf8, 0xce, 0x56, 0xfa, 0x4e, 0xb2, + 0x50, 0x06, 0x57, 0x87, 0x77, 0x47, 0xb9, 0x19, 0x38, 0xa5, 0x8e, 0xa7, + 0xdd, 0x0d, 0x3b, 0xa2, 0xdb, 0x52, 0xd1, 0x68, 0xf7, 0x40, 0xba, 0x60, + 0x35, 0xbb, 0x9a, 0xb4, 0x4e, 0x55, 0x8a, 0xa5, 0x7e, 0x47, 0xb3, 0x7f, + 0x51, 0xbf, 0xac, 0xd9, 0x8d, 0x24, 0x77, 0xac, 0x5a, 0x41, 0x74, 0x7b, + 0x29, 0x6c, 0x42, 0x65, 0xe7, 0xa4, 0x54, 0xe4, 0xf8, 0x00, 0x59, 0xd4, + 0x75, 0x47, 0xa3, 0xa7, 0x1e, 0x3e, 0x95, 0x29, 0xc6, 0xa1, 0x55, 0x93, + 0xc1, 0xb7, 0xef, 0xc0, 0x0f, 0xde, 0xa9, 0x53, 0x88, 0xf2, 0x51, 0x44, + 0xfe, 0xb8, 0x4c, 0x95, 0xd2, 0xc5, 0xaa, 0x47, 0xaa, 0x0c, 0xfd, 0xf3, + 0x8d, 0x8e, 0x54, 0xf7, 0xa7, 0x69, 0x56, 0xe8, 0xc7, 0x1c, 0xa7, 0xbe, + 0x01, 0xc6, 0xc2, 0x2e, 0x7c, 0xf2, 0xbc, 0xfa, 0xd9, 0xc9, 0x7e, 0x3f, + 0x3b, 0xfd, 0xa0, 0xb3, 0xd3, 0x8f, 0x39, 0xba, 0xac, 0x49, 0x0d, 0xcb, + 0x22, 0x2b, 0xf2, 0x15, 0x5d, 0x92, 0x4a, 0x43, 0xb9, 0x26, 0xb6, 0xde, + 0x35, 0xe4, 0x5a, 0x58, 0x6d, 0xad, 0x76, 0x68, 0x0b, 0xbb, 0xb9, 0x88, + 0xd8, 0xda, 0xea, 0x14, 0x15, 0xf2, 0x77, 0xdd, 0x13, 0x99, 0x2c, 0xcc, + 0xe5, 0x6c, 0x2c, 0x5e, 0x48, 0xaa, 0x86, 0x7b, 0x09, 0x3a, 0xf1, 0x1e, + 0xfc, 0x20, 0xa4, 0x40, 0x81, 0xe5, 0xbb, 0x4a, 0xca, 0x97, 0x7d, 0xf4, + 0x84, 0xa4, 0x6c, 0x23, 0xb4, 0x74, 0xe3, 0x67, 0xf2, 0xc8, 0x20, 0xef, + 0x09, 0x51, 0xe2, 0x55, 0x49, 0x82, 0x7a, 0xe6, 0xee, 0x9d, 0x90, 0x7e, + 0x57, 0x23, 0x21, 0x61, 0x7f, 0xfb, 0x19, 0x2e, 0xd0, 0xe2, 0x9c, 0xae, + 0x06, 0xba, 0x3d, 0xa1, 0x90, 0x2c, 0xfb, 0xc6, 0xfd, 0xe1, 0xad, 0xaf, + 0x3f, 0xee, 0xb3, 0x29, 0xf7, 0x29, 0x68, 0xd6, 0x1d, 0x51, 0x51, 0x54, + 0xb6, 0x4b, 0x30, 0xec, 0x42, 0xa3, 0x12, 0x2e, 0x40, 0x74, 0x62, 0x37, + 0xc0, 0x46, 0xc3, 0x1d, 0x46, 0x56, 0x6b, 0x01, 0x24, 0xe3, 0xd9, 0x88, + 0x4f, 0xd3, 0xef, 0x49, 0x02, 0x2c, 0xab, 0x3c, 0xf3, 0xaa, 0xaa, 0x82, + 0xc6, 0x5b, 0xdf, 0x40, 0xd1, 0xe1, 0x53, 0x80, 0xcb, 0x08, 0x25, 0x05, + 0x21, 0xb2, 0xf8, 0x89, 0x39, 0x0f, 0x5f, 0xf6, 0xf4, 0x45, 0x6f, 0xfc, + 0xe8, 0x45, 0xe4, 0xd1, 0xa8, 0x83, 0x5a, 0xec, 0x51, 0x2e, 0x9d, 0xca, + 0xff, 0x28, 0x3e, 0xe7, 0xc3, 0x59, 0x23, 0xdf, 0x7d, 0x89, 0x91, 0xdd, + 0x94, 0xbe, 0x79, 0x24, 0x14, 0xc9, 0x1a, 0xa0, 0x10, 0x88, 0xdc, 0xb6, + 0xc1, 0x33, 0x6a, 0xd8, 0x12, 0xb3, 0x6a, 0x68, 0x04, 0x72, 0x80, 0xe5, + 0xff, 0xb0, 0x00, 0xab, 0xf9, 0xbd, 0xb5, 0x67, 0x7f, 0x17, 0xed, 0xed, + 0xbc, 0x75, 0x8d, 0x94, 0x21, 0xbf, 0x9d, 0x06, 0x09, 0xc7, 0xbf, 0xad, + 0x16, 0x5b, 0xdf, 0x5b, 0x8b, 0x8d, 0x32, 0x17, 0xb8, 0x17, 0x00, 0x30, + 0x85, 0xfb, 0xd5, 0x86, 0x76, 0x9a, 0x24, 0xd4, 0xda, 0x4b, 0x41, 0xb2, + 0x2e, 0x28, 0x56, 0x28, 0x95, 0xd8, 0x14, 0x0b, 0xbd, 0x52, 0x3e, 0xac, + 0x16, 0xfe, 0x2b, 0xda, 0xa4, 0x85, 0x92, 0xa0, 0x49, 0xb1, 0x28, 0x97, + 0x7e, 0x76, 0x93, 0x7d, 0xd5, 0x0a, 0xe1, 0x46, 0xd2, 0xfd, 0x16, 0x1e, + 0xd0, 0x44, 0x55, 0x53, 0x6b, 0x70, 0xc1, 0x25, 0x5a, 0x18, 0xb5, 0xd7, + 0xa4, 0xf0, 0xd9, 0xe4, 0x92, 0xeb, 0xaf, 0x63, 0x5e, 0x6d, 0x03, 0xf3, + 0x6a, 0x4a, 0xe6, 0xa5, 0x41, 0x87, 0x66, 0x90, 0xdb, 0x05, 0x80, 0x6b, + 0xa1, 0x08, 0xcb, 0xe0, 0x39, 0x1f, 0x65, 0x02, 0xe2, 0x5c, 0x5b, 0x25, + 0x25, 0x17, 0x9a, 0x69, 0x64, 0x58, 0x6f, 0xf4, 0x22, 0x79, 0x45, 0x40, + 0x55, 0xf9, 0x52, 0x11, 0xd1, 0xaf, 0xe5, 0x0f, 0x66, 0xab, 0x96, 0x06, + 0x6f, 0x91, 0x98, 0xda, 0x38, 0x5c, 0x43, 0xdf, 0x7a, 0xe6, 0xf5, 0x80, + 0xe5, 0x37, 0xdb, 0x74, 0x40, 0x43, 0xc5, 0x33, 0xad, 0x96, 0x41, 0x31, + 0x02, 0xfb, 0x2c, 0x1f, 0xfb, 0x64, 0x32, 0x37, 0xf1, 0xb9, 0x88, 0xa5, + 0x5d, 0xad, 0xa0, 0x4e, 0x64, 0x98, 0x55, 0xcd, 0xaa, 0xf8, 0x19, 0x95, + 0xd6, 0x81, 0x23, 0x9c, 0x95, 0x40, 0x7e, 0x1b, 0xac, 0x43, 0x70, 0x94, + 0x65, 0x3c, 0x8b, 0x65, 0xed, 0x65, 0xca, 0xcd, 0x49, 0x52, 0xfd, 0x79, + 0x3d, 0x83, 0x57, 0xf6, 0x19, 0x53, 0x59, 0x9a, 0x6a, 0x9e, 0x55, 0x4d, + 0xbc, 0x51, 0x66, 0xe2, 0x19, 0xb2, 0x3f, 0x3e, 0x04, 0xc4, 0xb4, 0xa0, + 0xb1, 0xc4, 0xba, 0xf3, 0x28, 0x32, 0xdc, 0x99, 0x19, 0xe1, 0x07, 0xcb, + 0x7d, 0xa9, 0x92, 0x4a, 0xda, 0xe9, 0x11, 0xe7, 0x8f, 0xbb, 0x49, 0x1f, + 0x9f, 0x30, 0x47, 0x9f, 0x9f, 0x74, 0x4b, 0xe5, 0x9e, 0xb2, 0x8f, 0x1a, + 0x24, 0x3a, 0xce, 0x37, 0x6c, 0x7f, 0x28, 0x8c, 0xf6, 0x2a, 0x29, 0xc9, + 0x63, 0x1f, 0x01, 0x99, 0x29, 0x5e, 0xfd, 0xdc, 0x46, 0xae, 0xfc, 0x1d, + 0x8f, 0xec, 0xbb, 0x08, 0x26, 0x6f, 0xe0, 0x00, 0xc3, 0x20, 0xa5, 0x7b, + 0xc1, 0x06, 0x4f, 0x93, 0xc0, 0xb4, 0xb0, 0xe4, 0x09, 0x36, 0x0e, 0x35, + 0x77, 0x95, 0x13, 0x04, 0x4f, 0xa5, 0x7f, 0xe3, 0x32, 0xd1, 0x92, 0x6f, + 0x40, 0xe7, 0x90, 0x90, 0x4a, 0x3e, 0xb0, 0xc9, 0x5f, 0x70, 0x99, 0x7e, + 0xad, 0x59, 0xef, 0xb1, 0x93, 0x3a, 0xb4, 0x95, 0xf2, 0x6b, 0xcd, 0xfa, + 0x67, 0x8a, 0x09, 0x4c, 0xce, 0xd5, 0x00, 0x91, 0x2f, 0x52, 0x93, 0x4f, + 0x96, 0xf2, 0x77, 0x25, 0x6c, 0x94, 0xc0, 0x66, 0xa2, 0x7f, 0x50, 0x99, + 0x01, 0xa8, 0x55, 0x63, 0xac, 0xaf, 0x01, 0x28, 0x8e, 0x37, 0x91, 0xa1, + 0x8a, 0xa5, 0xbe, 0x44, 0x0c, 0x1a, 0xab, 0x86, 0xa9, 0xbe, 0x44, 0x30, + 0xfb, 0x92, 0x33, 0x63, 0x81, 0xd6, 0x01, 0xf6, 0x04, 0xc9, 0x77, 0x10, + 0x80, 0xe5, 0xa9, 0x7f, 0x44, 0x3d, 0x27, 0xdf, 0x91, 0x09, 0x36, 0x1b, + 0xe4, 0xd2, 0xf2, 0xba, 0x3f, 0x10, 0xe6, 0x03, 0xbc, 0x99, 0xd5, 0x3f, + 0xe8, 0xee, 0xe7, 0xd5, 0x80, 0x1e, 0xf1, 0x01, 0x29, 0x4a, 0x33, 0x32, + 0x9e, 0x4f, 0x51, 0x92, 0x08, 0x4a, 0x3c, 0x4b, 0x1a, 0x92, 0x6f, 0x9e, + 0xe6, 0xc2, 0xe5, 0xe2, 0x6e, 0xa3, 0xd3, 0xd7, 0x37, 0xf7, 0x64, 0x82, + 0xff, 0x23, 0x4b, 0xfc, 0x10, 0x61, 0x89, 0x63, 0x7d, 0x6e, 0xd9, 0xbb, + 0x1a, 0xb4, 0x62, 0x0f, 0xa7, 0x3e, 0x93, 0xe5, 0x87, 0xbd, 0xb9, 0x47, + 0xdd, 0x40, 0x1c, 0xb0, 0xdf, 0x07, 0xde, 0x1a, 0x7d, 0xb6, 0x81, 0x05, + 0x54, 0x58, 0x84, 0xc5, 0x8e, 0x79, 0x69, 0x58, 0xf6, 0x32, 0x16, 0x77, + 0x91, 0xfb, 0x94, 0x37, 0x10, 0x54, 0x1c, 0xf3, 0x01, 0x5a, 0x41, 0x52, + 0x91, 0x9b, 0x4c, 0xd7, 0x83, 0x3e, 0x7b, 0x7c, 0xd4, 0x57, 0x9b, 0x99, + 0x46, 0xf4, 0xcc, 0x2b, 0x7f, 0x88, 0xd7, 0x78, 0xd8, 0x06, 0x5f, 0xe5, + 0x95, 0x39, 0x9b, 0x0e, 0xd9, 0xe0, 0x2b, 0xd0, 0x02, 0xc2, 0x6b, 0x72, + 0x30, 0x11, 0xc0, 0xe7, 0xe8, 0xf6, 0x50, 0xfe, 0xfd, 0xf5, 0xb2, 0x48, + 0xc4, 0xe4, 0x7b, 0xf2, 0x04, 0xe3, 0x2a, 0xb5, 0xf6, 0x73, 0x13, 0xa6, + 0x76, 0xed, 0xd9, 0x21, 0x9f, 0x98, 0x26, 0x4e, 0x0b, 0x0e, 0xd8, 0xcf, + 0xf5, 0x7e, 0xa5, 0xa9, 0x67, 0xa2, 0xf7, 0x29, 0x93, 0x30, 0xd8, 0x3b, + 0x0f, 0xc4, 0x92, 0x6e, 0x9c, 0x1b, 0x68, 0xf5, 0xea, 0x1d, 0x45, 0x5e, + 0x42, 0xd5, 0xbe, 0x85, 0x5e, 0x26, 0xa6, 0x4a, 0x5f, 0x76, 0xb7, 0xcd, + 0x3e, 0x77, 0x5d, 0xf9, 0xbb, 0xed, 0xc2, 0x67, 0xd4, 0xcb, 0xf8, 0xbe, + 0xe5, 0x97, 0xc8, 0xcb, 0xf9, 0x56, 0xfb, 0xce, 0x78, 0x09, 0x6e, 0x5c, + 0x69, 0x3c, 0xf4, 0x8d, 0x9f, 0x1e, 0x37, 0xba, 0x05, 0xbd, 0x73, 0x57, + 0x8a, 0xc7, 0x39, 0x06, 0x6f, 0x92, 0xc5, 0x0b, 0x1d, 0x9e, 0x05, 0x6a, + 0x18, 0xbc, 0x7b, 0xe2, 0x53, 0x7b, 0x24, 0x0f, 0x3a, 0x59, 0xfe, 0x5c, + 0x17, 0x86, 0xf2, 0x46, 0x32, 0xbd, 0xea, 0xe2, 0x4b, 0xa0, 0xf7, 0x44, + 0xf8, 0x52, 0xd5, 0x45, 0x24, 0xa7, 0x5f, 0xbe, 0xc6, 0xae, 0xf6, 0x2a, + 0x92, 0x93, 0x47, 0x8f, 0x41, 0x18, 0x6b, 0xeb, 0x21, 0x38, 0x3d, 0xcd, + 0xdf, 0x68, 0x2a, 0x23, 0x24, 0x6a, 0x7b, 0x61, 0xd5, 0xd9, 0xff, 0x81, + 0xef, 0xf0, 0x2a, 0xcb, 0x02, 0x66, 0xde, 0x03, 0x39, 0x7b, 0x90, 0xd0, + 0x39, 0x7e, 0x85, 0xf0, 0x5f, 0x1b, 0x7a, 0xe7, 0x74, 0x43, 0xee, 0x3b, + 0xc9, 0xbb, 0xa4, 0x52, 0x3e, 0x06, 0x38, 0x2a, 0x24, 0x36, 0x74, 0xc8, + 0xe6, 0x1e, 0x9f, 0xb2, 0xfc, 0x55, 0x81, 0x49, 0x21, 0x4a, 0x29, 0x8f, + 0x16, 0xc8, 0x96, 0x92, 0x85, 0x9c, 0x85, 0xb8, 0x0c, 0x48, 0xbc, 0x55, + 0x01, 0xc3, 0xcc, 0xb1, 0xbf, 0x83, 0x22, 0x5a, 0x81, 0xb5, 0xd1, 0x2d, + 0x68, 0x12, 0x28, 0x0f, 0xbc, 0x27, 0x2f, 0x02, 0xd1, 0x0d, 0x0c, 0xf6, + 0x6f, 0x96, 0x07, 0x2d, 0xdd, 0x49, 0x8d, 0x20, 0x32, 0xc9, 0x9e, 0xff, + 0x90, 0x7c, 0xed, 0x30, 0xb9, 0xe9, 0xa7, 0x88, 0x54, 0x91, 0x1b, 0x1f, + 0xf6, 0x90, 0x9f, 0xe1, 0x09, 0x49, 0xc1, 0x43, 0x68, 0x4a, 0xed, 0x0b, + 0x2c, 0xea, 0x45, 0x67, 0xc1, 0x6b, 0xd0, 0x21, 0x1e, 0x45, 0x26, 0x78, + 0xa5, 0x79, 0x7f, 0x00, 0x87, 0x2a, 0xfd, 0x49, 0x85, 0x3c, 0xc5, 0x3f, + 0xae, 0x74, 0x1a, 0x07, 0x47, 0x50, 0x52, 0x40, 0x7f, 0x90, 0x8b, 0x24, + 0x6d, 0x71, 0x14, 0x5f, 0x8e, 0xd8, 0xa4, 0x7e, 0xdd, 0x00, 0xfa, 0x64, + 0xab, 0xa1, 0x77, 0xad, 0x2c, 0x9c, 0xc3, 0x6a, 0x64, 0xe7, 0x65, 0x33, + 0x48, 0xf9, 0x5c, 0x23, 0x43, 0x58, 0xf9, 0x5c, 0xab, 0x23, 0xa0, 0xe5, + 0xc9, 0xde, 0x04, 0x5c, 0x24, 0x80, 0x59, 0xa5, 0x0a, 0xc6, 0x4c, 0xd7, + 0xed, 0xdb, 0xd8, 0xb2, 0x55, 0xcd, 0x0e, 0xf5, 0x47, 0x2d, 0x95, 0x1d, + 0xea, 0x7d, 0xa8, 0xc2, 0x0e, 0xf5, 0x4e, 0xdc, 0x3f, 0xec, 0xd2, 0x76, + 0x2d, 0xc0, 0x7e, 0xd5, 0x37, 0x11, 0xef, 0xf6, 0xfb, 0x23, 0xec, 0x77, + 0xee, 0xbe, 0xc4, 0x07, 0x7c, 0xba, 0x4e, 0xa2, 0x4a, 0x72, 0xa5, 0x87, + 0x7f, 0x4f, 0xee, 0x23, 0xea, 0xa8, 0x7f, 0x71, 0xb9, 0xb8, 0x1e, 0x0f, + 0x86, 0xbf, 0x5a, 0x60, 0x5e, 0xcc, 0x0d, 0x6b, 0xec, 0x80, 0x4e, 0x5e, + 0x18, 0x28, 0x11, 0xe2, 0x1a, 0x85, 0x54, 0x16, 0x10, 0xcb, 0xb9, 0x84, + 0x4d, 0x02, 0xbf, 0x44, 0x6e, 0xe7, 0x42, 0x54, 0x04, 0x49, 0x69, 0x02, + 0x56, 0xa7, 0x0c, 0x0e, 0xf3, 0x0c, 0xe3, 0x72, 0x86, 0x8d, 0xca, 0x0c, + 0xa3, 0x52, 0x86, 0x1c, 0x2c, 0x50, 0x7d, 0x63, 0x87, 0x3e, 0x87, 0xce, + 0x5e, 0x7a, 0x1f, 0x09, 0x81, 0xf8, 0xaa, 0x6d, 0x95, 0x36, 0x27, 0x95, + 0x51, 0x68, 0x3a, 0x9c, 0x0c, 0xbb, 0x73, 0xad, 0x9d, 0xf2, 0x06, 0xfd, + 0x51, 0xf7, 0x7a, 0xa2, 0xb5, 0x50, 0x4e, 0x7f, 0x7d, 0x35, 0x9d, 0x8e, + 0xa7, 0xda, 0x98, 0x97, 0x37, 0xe8, 0x8d, 0xa7, 0x83, 0xe1, 0x54, 0x1b, + 0xf4, 0xe6, 0x7b, 0x58, 0x8c, 0x6f, 0xfa, 0xc3, 0x62, 0xec, 0x5b, 0xb2, + 0x06, 0xe6, 0xa5, 0x52, 0x34, 0x58, 0xf1, 0xef, 0x52, 0x24, 0x91, 0x5d, + 0xa9, 0x14, 0x0d, 0xee, 0x08, 0xde, 0xa5, 0x48, 0x22, 0x78, 0xf7, 0x39, + 0xa9, 0x98, 0x4b, 0xab, 0x25, 0xe0, 0xb7, 0xca, 0xf2, 0x36, 0xad, 0xdd, + 0xed, 0xc9, 0xb1, 0x3c, 0x78, 0x2e, 0xb2, 0xd1, 0xef, 0xd9, 0xfd, 0xc0, + 0xdd, 0x6c, 0xbc, 0x95, 0x47, 0x92, 0x33, 0xdb, 0x20, 0xf8, 0xfd, 0xb0, + 0x57, 0x8c, 0xc8, 0xfc, 0x93, 0x94, 0xdd, 0x43, 0x1c, 0x8c, 0xc6, 0x83, + 0xff, 0x26, 0x49, 0x5a, 0xb4, 0xf4, 0xf0, 0xa1, 0x2a, 0xf0, 0xb7, 0x00, + 0x42, 0x84, 0x3e, 0x7d, 0xd5, 0x23, 0x8d, 0xa3, 0xc3, 0x7e, 0xbf, 0xf5, + 0xa0, 0x90, 0x44, 0x9f, 0xa8, 0xbf, 0x74, 0xc8, 0x83, 0x42, 0x54, 0xfa, + 0x45, 0x5b, 0x7d, 0x64, 0x7e, 0xe1, 0xc6, 0xab, 0xc7, 0x72, 0x26, 0x85, + 0x20, 0xbd, 0xc8, 0x65, 0xc4, 0xa4, 0x0b, 0xe7, 0x24, 0xe4, 0x4c, 0x34, + 0x68, 0x7c, 0xe9, 0x2e, 0x6c, 0x0f, 0xb4, 0x2b, 0x87, 0x93, 0xa6, 0xe8, + 0x1c, 0x9a, 0xa5, 0x93, 0x36, 0x68, 0x0c, 0xb4, 0x8b, 0x26, 0x25, 0xed, + 0x1f, 0x96, 0x04, 0xcf, 0x79, 0xaf, 0x5d, 0x34, 0x69, 0x03, 0x6b, 0xa0, + 0xcd, 0x58, 0x70, 0x52, 0x06, 0x89, 0xa3, 0x4d, 0x59, 0x64, 0x83, 0x79, + 0xf4, 0xb0, 0x9c, 0x69, 0xe9, 0x4d, 0x31, 0x71, 0x21, 0x5d, 0xf6, 0x1d, + 0x11, 0xe4, 0x58, 0x9a, 0x20, 0x27, 0x6d, 0x19, 0xd1, 0xa4, 0x58, 0x48, + 0x53, 0x61, 0x68, 0x49, 0xc0, 0x7c, 0xaa, 0x7e, 0xb3, 0xa1, 0x90, 0x93, + 0x88, 0xc9, 0xbd, 0xd0, 0x33, 0xe1, 0xd7, 0x20, 0xa7, 0xfe, 0x38, 0xe9, + 0x09, 0xbe, 0x52, 0xd4, 0x1f, 0x14, 0x45, 0x86, 0xb6, 0x9e, 0xa1, 0xfe, + 0x00, 0x29, 0x32, 0xb4, 0xf4, 0x0c, 0xf5, 0x37, 0x96, 0x22, 0xc3, 0xba, + 0x9e, 0x21, 0x08, 0xab, 0xaa, 0x55, 0xb1, 0xee, 0xf3, 0x36, 0x23, 0xf7, + 0x09, 0x07, 0x72, 0x75, 0x52, 0x06, 0x46, 0x4e, 0x18, 0xab, 0x78, 0xfb, + 0x0a, 0x7f, 0xef, 0xd3, 0x2e, 0xa2, 0x80, 0x28, 0x99, 0x91, 0x8f, 0x86, + 0xaa, 0xe2, 0x5f, 0xbb, 0xa5, 0x17, 0x75, 0xca, 0xe7, 0xb6, 0xb7, 0x98, + 0x74, 0x81, 0x4a, 0x69, 0xdb, 0xa4, 0x62, 0x98, 0x42, 0x4c, 0x51, 0x4e, + 0x10, 0x03, 0x7d, 0x02, 0xea, 0x82, 0xe4, 0x29, 0x11, 0x71, 0xcb, 0x40, + 0x7a, 0xc8, 0xe6, 0x49, 0x8e, 0xa8, 0xa3, 0x40, 0x3a, 0xbc, 0x76, 0x5e, + 0x58, 0xff, 0xb5, 0x60, 0x53, 0x1b, 0xb8, 0xb1, 0xe3, 0x6d, 0x21, 0x4e, + 0xf5, 0x8e, 0x9e, 0x93, 0xe7, 0x1b, 0x70, 0xb2, 0xce, 0xed, 0x3c, 0x27, + 0x40, 0x2a, 0x41, 0xc8, 0x92, 0xf1, 0xa4, 0xce, 0x8e, 0x3e, 0x88, 0x86, + 0x38, 0x9d, 0xe9, 0xd1, 0x67, 0x24, 0x46, 0x4b, 0xa1, 0x82, 0x5a, 0x42, + 0xbc, 0xd4, 0x8b, 0x59, 0xe2, 0xf3, 0x40, 0x50, 0xfd, 0x21, 0x46, 0x06, + 0xe5, 0x55, 0x12, 0xa3, 0x10, 0x86, 0xd7, 0x37, 0x46, 0x68, 0x98, 0xd1, + 0xeb, 0xdc, 0x39, 0xa2, 0xb0, 0x52, 0xab, 0x60, 0x47, 0x0a, 0x7e, 0x42, + 0xf7, 0x5f, 0x07, 0xf0, 0xaa, 0xda, 0x32, 0x38, 0xf6, 0x53, 0xae, 0xc3, + 0x79, 0x1f, 0xc2, 0x7e, 0xa0, 0xa5, 0x33, 0xea, 0x10, 0x08, 0xe6, 0x95, + 0x3a, 0x8b, 0xaf, 0xa8, 0xfb, 0xe2, 0x41, 0x9f, 0x93, 0xb4, 0x0d, 0xee, + 0xf6, 0x45, 0x46, 0x5f, 0x94, 0x8c, 0x0c, 0xe0, 0x7f, 0x66, 0xcf, 0xde, + 0x1f, 0x7f, 0x90, 0x78, 0x08, 0x88, 0x97, 0x39, 0x72, 0xbd, 0x3a, 0x60, + 0x4e, 0xdb, 0x13, 0x0c, 0x68, 0xed, 0x96, 0x9f, 0x12, 0x8f, 0x85, 0xef, + 0xe3, 0xaa, 0x76, 0xfb, 0x94, 0x76, 0x2a, 0xdc, 0x39, 0xa8, 0xb6, 0xfb, + 0x94, 0xf6, 0x92, 0x59, 0xa1, 0x66, 0xaf, 0x4f, 0xa9, 0x7b, 0xd4, 0xf6, + 0x35, 0xbb, 0x7d, 0x26, 0x1f, 0xb6, 0xe2, 0x2a, 0x3c, 0x97, 0xca, 0xba, + 0x01, 0x24, 0x6b, 0x19, 0x14, 0xc9, 0xa5, 0x73, 0x82, 0x9a, 0x17, 0xde, + 0xcd, 0x29, 0x9b, 0x4f, 0xa1, 0xe6, 0x06, 0x25, 0x8a, 0x0c, 0x4a, 0xb8, + 0x80, 0x61, 0x0f, 0x1c, 0xaa, 0xb2, 0x53, 0x00, 0x04, 0x78, 0x0f, 0xe4, + 0xb4, 0xa6, 0x97, 0x3d, 0xc0, 0x56, 0xeb, 0x06, 0x30, 0x2a, 0xe9, 0xd6, + 0x28, 0xde, 0x9f, 0x08, 0xf9, 0xb4, 0xba, 0x01, 0xf6, 0x18, 0x2b, 0x7c, + 0xa6, 0x93, 0xcb, 0x06, 0x21, 0xc0, 0x86, 0xeb, 0xbd, 0xa7, 0x58, 0x39, + 0x0d, 0x70, 0x30, 0xf8, 0x44, 0xa4, 0x00, 0x08, 0x04, 0x30, 0x68, 0x19, + 0x38, 0x3a, 0x86, 0xc4, 0x98, 0x54, 0x73, 0x9f, 0xb4, 0x9b, 0x35, 0x72, + 0xd3, 0x86, 0xf7, 0x04, 0x7a, 0x53, 0xc5, 0x5f, 0x4c, 0x95, 0x21, 0x23, + 0xab, 0x85, 0x4b, 0x63, 0xc2, 0x3d, 0x29, 0x15, 0xe3, 0x97, 0x34, 0x95, + 0x2f, 0x44, 0x09, 0x98, 0x2e, 0x3e, 0xb0, 0xb1, 0xc3, 0xe3, 0x85, 0xb7, + 0x15, 0x79, 0x15, 0x03, 0x2d, 0xa5, 0xa8, 0xae, 0x9d, 0x07, 0x25, 0x1f, + 0x15, 0x6e, 0x1c, 0x10, 0x5f, 0xb9, 0xfe, 0x61, 0x97, 0x9b, 0x25, 0x45, + 0xb4, 0x64, 0xcf, 0x10, 0xb3, 0xea, 0x6d, 0x28, 0x66, 0x17, 0xe8, 0xd0, + 0x14, 0x80, 0x52, 0x31, 0x68, 0x84, 0x66, 0x37, 0xe3, 0xe9, 0x35, 0x80, + 0x3d, 0xa6, 0x6d, 0x7a, 0x09, 0xbd, 0x5f, 0x36, 0x68, 0x95, 0xeb, 0xb1, + 0x51, 0xa1, 0x6d, 0xaf, 0xdb, 0x01, 0x52, 0x05, 0x46, 0xed, 0x72, 0xbd, + 0xb6, 0xaa, 0xb4, 0x16, 0xe1, 0x57, 0xda, 0x95, 0xba, 0xe5, 0x8f, 0x11, + 0xcf, 0x2a, 0x75, 0xb8, 0xe8, 0xf2, 0xef, 0xc4, 0x77, 0xaa, 0xb4, 0xb4, + 0xea, 0x8b, 0x2e, 0x7f, 0x9e, 0x7e, 0x6e, 0xde, 0x54, 0x78, 0x0e, 0x69, + 0x55, 0xb0, 0x1f, 0xab, 0x9d, 0x37, 0xa0, 0x2a, 0x16, 0x24, 0x76, 0x5a, + 0xc5, 0x86, 0x8a, 0xbd, 0x56, 0xb3, 0x22, 0xb1, 0xdf, 0x6a, 0x76, 0x54, + 0xec, 0xb9, 0x82, 0x25, 0x59, 0xed, 0x0b, 0xde, 0xae, 0x8a, 0x21, 0x49, + 0x0d, 0x2b, 0x59, 0x52, 0x57, 0x6a, 0x5a, 0xc1, 0x94, 0x2c, 0xeb, 0x62, + 0x71, 0x49, 0xfe, 0x81, 0x4d, 0x4a, 0xe0, 0x50, 0xc1, 0xa2, 0x2e, 0x7b, + 0xe7, 0x8b, 0x21, 0x5f, 0x38, 0xb6, 0xb9, 0x55, 0x0d, 0x86, 0x93, 0xf9, + 0x27, 0xd4, 0x1f, 0x5f, 0x4f, 0xc4, 0x47, 0xba, 0xe6, 0x86, 0xc5, 0xdb, + 0x0b, 0xaf, 0x81, 0x6d, 0x73, 0x03, 0xe3, 0xed, 0x1b, 0x36, 0x9f, 0xbb, + 0x6d, 0x6e, 0x63, 0x94, 0x81, 0xdd, 0x5c, 0x7c, 0x11, 0x5c, 0x64, 0x05, + 0x3b, 0x13, 0x06, 0x5d, 0xc5, 0xba, 0x78, 0x2b, 0x6e, 0x5b, 0xa4, 0x34, + 0x3f, 0xbd, 0x37, 0x3d, 0xf8, 0x1b, 0xba, 0x47, 0xe1, 0xe3, 0x27, 0xbd, + 0x71, 0x4b, 0xd3, 0x71, 0xd9, 0xc3, 0x2c, 0x5d, 0x17, 0x33, 0x61, 0x3a, + 0x67, 0xba, 0x2e, 0x92, 0x4f, 0xb4, 0x56, 0xee, 0x43, 0x54, 0x79, 0x47, + 0xd7, 0x49, 0xf2, 0xa5, 0xd2, 0xaa, 0x9d, 0x4c, 0x25, 0xbd, 0x9e, 0xeb, + 0x7a, 0x21, 0x31, 0xcc, 0x31, 0xbd, 0x5c, 0x8a, 0xdd, 0x70, 0xb8, 0x1f, + 0xa5, 0xc4, 0xec, 0xe3, 0xd4, 0x42, 0x96, 0xb9, 0xd4, 0x93, 0x90, 0xe1, + 0x36, 0x68, 0xdb, 0x59, 0xe0, 0xf3, 0xa3, 0x00, 0x87, 0x56, 0xc5, 0x11, + 0xe3, 0xc6, 0x93, 0xdb, 0x9b, 0xfe, 0xa7, 0xf9, 0xa7, 0xe9, 0xf8, 0xf6, + 0xf2, 0xd3, 0xa2, 0x3b, 0x9a, 0x7c, 0x12, 0xb6, 0x2e, 0x06, 0x32, 0x64, + 0xec, 0x71, 0x16, 0xc3, 0x6e, 0x9f, 0xb7, 0x35, 0x5f, 0x30, 0xb3, 0xab, + 0xcb, 0x9b, 0xe1, 0x60, 0x51, 0xe0, 0x50, 0x65, 0x93, 0xcf, 0xb7, 0x35, + 0x77, 0xcf, 0x69, 0xef, 0x05, 0x16, 0x67, 0x95, 0xd4, 0xd0, 0x65, 0x7a, + 0x90, 0x59, 0x98, 0x3b, 0xec, 0xaf, 0xfd, 0x5e, 0x7f, 0xba, 0x18, 0xdd, + 0x5e, 0x77, 0x79, 0x6b, 0x73, 0x67, 0xcd, 0x5a, 0x37, 0xed, 0xfa, 0xa2, + 0x8f, 0x35, 0x29, 0xf0, 0x68, 0xd6, 0xcd, 0x27, 0xd1, 0xeb, 0x73, 0xcd, + 0x37, 0xcd, 0x47, 0xde, 0x13, 0x8c, 0xaf, 0x69, 0x3e, 0xe4, 0x5e, 0xbf, + 0xc1, 0xa3, 0xb9, 0x0a, 0xa3, 0xec, 0xce, 0xe6, 0xfd, 0x45, 0xf3, 0x45, + 0xc0, 0xdd, 0x33, 0x37, 0x34, 0xda, 0xb6, 0x25, 0xb6, 0x35, 0x37, 0xb1, + 0xa4, 0xad, 0x10, 0x49, 0x9a, 0x9b, 0x18, 0x6d, 0xdb, 0x16, 0xdb, 0x9a, + 0x07, 0x01, 0x49, 0x5b, 0xee, 0x55, 0xdb, 0xe6, 0xaa, 0xa1, 0x6d, 0x3b, + 0x62, 0xbf, 0xe6, 0xfa, 0x49, 0xda, 0xf2, 0x7e, 0xcf, 0xcc, 0x03, 0x80, + 0xa4, 0x2d, 0xdf, 0x6e, 0xce, 0xcc, 0x37, 0x7f, 0xda, 0xd6, 0xaa, 0x0b, + 0x83, 0x3e, 0x33, 0xf7, 0x68, 0x69, 0x63, 0x61, 0xd4, 0xe6, 0xbb, 0x7e, + 0xda, 0x58, 0x18, 0x76, 0x45, 0xd3, 0xc2, 0x8d, 0xc5, 0xf2, 0xcf, 0x8a, + 0xc6, 0x65, 0xd9, 0x52, 0xeb, 0x8a, 0xe6, 0x45, 0x5a, 0xf3, 0x85, 0x78, + 0x76, 0x96, 0x1e, 0x55, 0xc9, 0xf1, 0xf4, 0xb7, 0x9f, 0x7e, 0x39, 0x7d, + 0x5a, 0xbd, 0xec, 0xb6, 0xbf, 0xfd, 0xf4, 0x7f, 0xf9, 0x0b, 0x6a, 0x39, + +}; diff --git a/lib/mesa/src/broadcom/clif/clif_dump.c b/lib/mesa/src/broadcom/clif/clif_dump.c new file mode 100644 index 000000000..339fc3835 --- /dev/null +++ b/lib/mesa/src/broadcom/clif/clif_dump.c @@ -0,0 +1,281 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "clif_dump.h" +#include "util/list.h" +#include "util/ralloc.h" + +#include "broadcom/cle/v3d_decoder.h" + +#define __gen_user_data void +#define __gen_address_type uint32_t +#define __gen_address_offset(reloc) (*reloc) +#define __gen_emit_reloc(cl, reloc) +#define __gen_unpack_address(cl, s, e) (__gen_unpack_uint(cl, s, e) << (31 - (e - s))) + +enum reloc_worklist_type { + reloc_gl_shader_state, +}; + +struct reloc_worklist_entry { + struct list_head link; + + enum reloc_worklist_type type; + uint32_t addr; + + union { + struct { + uint32_t num_attrs; + } shader_state; + }; +}; + +struct clif_dump { + const struct v3d_device_info *devinfo; + bool (*lookup_vaddr)(void *data, uint32_t addr, void **vaddr); + FILE *out; + /* Opaque data from the caller that is passed to the callbacks. */ + void *data; + + struct v3d_spec *spec; + + /* List of struct reloc_worklist_entry */ + struct list_head worklist; +}; + +static void +out(struct clif_dump *clif, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + vfprintf(clif->out, fmt, args); + va_end(args); +} + +#include "broadcom/cle/v3d_packet_v33_pack.h" + +static struct reloc_worklist_entry * +clif_dump_add_address_to_worklist(struct clif_dump *clif, + enum reloc_worklist_type type, + uint32_t addr) +{ + struct reloc_worklist_entry *entry = + rzalloc(clif, struct reloc_worklist_entry); + if (!entry) + return NULL; + + entry->type = type; + entry->addr = addr; + + list_addtail(&entry->link, &clif->worklist); + + return entry; +} + +struct clif_dump * +clif_dump_init(const struct v3d_device_info *devinfo, + FILE *out, + bool (*lookup_vaddr)(void *data, uint32_t addr, void **vaddr), + void *data) +{ + struct clif_dump *clif = rzalloc(NULL, struct clif_dump); + + clif->devinfo = devinfo; + clif->lookup_vaddr = lookup_vaddr; + clif->out = out; + clif->data = data; + clif->spec = v3d_spec_load(devinfo); + + list_inithead(&clif->worklist); + + return clif; +} + +void +clif_dump_destroy(struct clif_dump *clif) +{ + ralloc_free(clif); +} + +#define out_uint(_clif, field) out(_clif, " /* %s = */ %u\n", \ + #field, values-> field); + +static bool +clif_dump_packet(struct clif_dump *clif, uint32_t offset, const uint8_t *cl, + uint32_t *size) +{ + struct v3d_group *inst = v3d_spec_find_instruction(clif->spec, cl); + if (!inst) { + out(clif, "0x%08x: Unknown packet %d!\n", offset, *cl); + return false; + } + + *size = v3d_group_get_length(inst); + + out(clif, "%s\n", v3d_group_get_name(inst)); + v3d_print_group(clif->out, inst, 0, cl, ""); + + switch (*cl) { + case V3D33_GL_SHADER_STATE_opcode: { + struct V3D33_GL_SHADER_STATE values; + V3D33_GL_SHADER_STATE_unpack(cl, &values); + + struct reloc_worklist_entry *reloc = + clif_dump_add_address_to_worklist(clif, + reloc_gl_shader_state, + values.address); + if (reloc) { + reloc->shader_state.num_attrs = + values.number_of_attribute_arrays; + } + return true; + } + + case V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_opcode: { + struct V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED values; + V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_unpack(cl, &values); + + if (values.last_tile_of_frame) + return false; + break; + } + + case V3D33_TRANSFORM_FEEDBACK_ENABLE_opcode: { + struct V3D33_TRANSFORM_FEEDBACK_ENABLE values; + V3D33_TRANSFORM_FEEDBACK_ENABLE_unpack(cl, &values); + struct v3d_group *spec = v3d_spec_find_struct(clif->spec, + "Transform Feedback Output Data Spec"); + struct v3d_group *addr = v3d_spec_find_struct(clif->spec, + "Transform Feedback Output Address"); + assert(spec); + assert(addr); + + cl += *size; + + for (int i = 0; i < values.number_of_16_bit_output_data_specs_following; i++) { + v3d_print_group(clif->out, spec, 0, cl, ""); + cl += v3d_group_get_length(spec); + *size += v3d_group_get_length(spec); + } + + for (int i = 0; i < values.number_of_32_bit_output_buffer_address_following; i++) { + v3d_print_group(clif->out, addr, 0, cl, ""); + cl += v3d_group_get_length(addr); + *size += v3d_group_get_length(addr); + } + break; + } + + case V3D33_HALT_opcode: + return false; + } + + return true; +} + +static void +clif_dump_gl_shader_state_record(struct clif_dump *clif, + struct reloc_worklist_entry *reloc, void *vaddr) +{ + struct v3d_group *state = v3d_spec_find_struct(clif->spec, + "GL Shader State Record"); + struct v3d_group *attr = v3d_spec_find_struct(clif->spec, + "GL Shader State Attribute Record"); + assert(state); + assert(attr); + + out(clif, "GL Shader State Record at 0x%08x\n", reloc->addr); + v3d_print_group(clif->out, state, 0, vaddr, ""); + vaddr += v3d_group_get_length(state); + + for (int i = 0; i < reloc->shader_state.num_attrs; i++) { + out(clif, " Attribute %d\n", i); + v3d_print_group(clif->out, attr, 0, vaddr, ""); + vaddr += v3d_group_get_length(attr); + } +} + +static void +clif_process_worklist(struct clif_dump *clif) +{ + while (!list_empty(&clif->worklist)) { + struct reloc_worklist_entry *reloc = + list_first_entry(&clif->worklist, + struct reloc_worklist_entry, link); + list_del(&reloc->link); + + void *vaddr; + if (!clif->lookup_vaddr(clif->data, reloc->addr, &vaddr)) { + out(clif, "Failed to look up address 0x%08x\n", + reloc->addr); + continue; + } + + switch (reloc->type) { + case reloc_gl_shader_state: + clif_dump_gl_shader_state_record(clif, reloc, vaddr); + break; + } + out(clif, "\n"); + } +} + +void +clif_dump_add_cl(struct clif_dump *clif, uint32_t start, uint32_t end) +{ + uint32_t size; + + void *start_vaddr; + if (!clif->lookup_vaddr(clif->data, start, &start_vaddr)) { + out(clif, "Failed to look up address 0x%08x\n", + start); + return; + } + + /* The end address is optional (for example, a BRANCH instruction + * won't set an end), but is used for BCL/RCL termination. + */ + void *end_vaddr = NULL; + if (end && !clif->lookup_vaddr(clif->data, end, &end_vaddr)) { + out(clif, "Failed to look up address 0x%08x\n", + end); + return; + } + + uint8_t *cl = start_vaddr; + while (clif_dump_packet(clif, start, cl, &size)) { + cl += size; + start += size; + + if (cl == end_vaddr) + break; + } + + out(clif, "\n"); + + clif_process_worklist(clif); +} diff --git a/lib/mesa/src/broadcom/clif/clif_dump.h b/lib/mesa/src/broadcom/clif/clif_dump.h new file mode 100644 index 000000000..d46cc8471 --- /dev/null +++ b/lib/mesa/src/broadcom/clif/clif_dump.h @@ -0,0 +1,42 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 CLIF_DUMP_H +#define CLIF_DUMP_H + +#include <stdbool.h> +#include <stdint.h> + +struct v3d_device_info; +struct clif_dump; + +struct clif_dump *clif_dump_init(const struct v3d_device_info *devinfo, + FILE *output, + bool (*lookup_vaddr)(void *data, uint32_t addr, + void **vaddr), + void *data); +void clif_dump_destroy(struct clif_dump *clif); + +void clif_dump_add_cl(struct clif_dump *clif, uint32_t start, uint32_t end); + +#endif diff --git a/lib/mesa/src/broadcom/common/v3d_debug.c b/lib/mesa/src/broadcom/common/v3d_debug.c new file mode 100644 index 000000000..630bfe0fc --- /dev/null +++ b/lib/mesa/src/broadcom/common/v3d_debug.c @@ -0,0 +1,89 @@ +/* + * Copyright 2003 VMware, Inc. + * Copyright © 2006 Intel Corporation + * Copyright © 2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/** + * \file v3d_debug.c + * + * Support for the V3D_DEBUG environment variable, along with other + * miscellaneous debugging code. + */ + +#include <stdlib.h> + +#include "common/v3d_debug.h" +#include "util/macros.h" +#include "util/debug.h" +#include "c11/threads.h" + +uint32_t V3D_DEBUG = 0; + +static const struct debug_control debug_control[] = { + { "cl", V3D_DEBUG_CL}, + { "qpu", V3D_DEBUG_QPU}, + { "vir", V3D_DEBUG_VIR}, + { "nir", V3D_DEBUG_NIR}, + { "tgsi", V3D_DEBUG_TGSI}, + { "shaderdb", V3D_DEBUG_SHADERDB}, + { "surface", V3D_DEBUG_SURFACE}, + { "perf", V3D_DEBUG_PERF}, + { "norast", V3D_DEBUG_NORAST}, + { "fs", V3D_DEBUG_FS}, + { "vs", V3D_DEBUG_VS}, + { "cs", V3D_DEBUG_CS}, + { NULL, 0 } +}; + +uint32_t +v3d_debug_flag_for_shader_stage(gl_shader_stage stage) +{ + uint32_t flags[] = { + [MESA_SHADER_VERTEX] = V3D_DEBUG_VS, + [MESA_SHADER_TESS_CTRL] = 0, + [MESA_SHADER_TESS_EVAL] = 0, + [MESA_SHADER_GEOMETRY] = 0, + [MESA_SHADER_FRAGMENT] = V3D_DEBUG_FS, + [MESA_SHADER_COMPUTE] = V3D_DEBUG_CS, + }; + STATIC_ASSERT(MESA_SHADER_STAGES == 6); + return flags[stage]; +} + +static void +v3d_process_debug_variable_once(void) +{ + V3D_DEBUG = parse_debug_string(getenv("V3D_DEBUG"), debug_control); + + if (V3D_DEBUG & V3D_DEBUG_SHADERDB) + V3D_DEBUG |= V3D_DEBUG_NORAST; +} + +void +v3d_process_debug_variable(void) +{ + static once_flag v3d_process_debug_variable_flag = ONCE_FLAG_INIT; + + call_once(&v3d_process_debug_variable_flag, + v3d_process_debug_variable_once); +} diff --git a/lib/mesa/src/broadcom/common/v3d_debug.h b/lib/mesa/src/broadcom/common/v3d_debug.h new file mode 100644 index 000000000..bdb951854 --- /dev/null +++ b/lib/mesa/src/broadcom/common/v3d_debug.h @@ -0,0 +1,82 @@ +/* + * Copyright 2003 VMware, Inc. + * Copyright © 2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE 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 MESA_V3D_DEBUG_H +#define MESA_V3D_DEBUG_H + +#include <stdint.h> +#include "compiler/shader_enums.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * \file v3d_debug.h + * + * Basic V3D_DEBUG environment variable handling. This file defines the + * list of debugging flags, as well as some macros for handling them. + */ + +extern uint32_t V3D_DEBUG; + +#define V3D_DEBUG_SHADERDB (1 << 0) +#define V3D_DEBUG_TGSI (1 << 1) +#define V3D_DEBUG_NIR (1 << 2) +#define V3D_DEBUG_VIR (1 << 3) +#define V3D_DEBUG_QPU (1 << 4) +#define V3D_DEBUG_FS (1 << 5) +#define V3D_DEBUG_VS (1 << 6) +#define V3D_DEBUG_CS (1 << 7) +#define V3D_DEBUG_CL (1 << 8) +#define V3D_DEBUG_SURFACE (1 << 9) +#define V3D_DEBUG_PERF (1 << 10) +#define V3D_DEBUG_NORAST (1 << 11) +#define V3D_DEBUG_ALWAYS_FLUSH (1 << 12) + +#ifdef HAVE_ANDROID_PLATFORM +#define LOG_TAG "BROADCOM-MESA" +#include <cutils/log.h> +#ifndef ALOGW +#define ALOGW LOGW +#endif +#define dbg_printf(...) ALOGW(__VA_ARGS__) +#else +#define dbg_printf(...) fprintf(stderr, __VA_ARGS__) +#endif /* HAVE_ANDROID_PLATFORM */ + +#define DBG(flag, ...) do { \ + if (unlikely(V3D_DEBUG & (flag))) \ + dbg_printf(__VA_ARGS__); \ +} while(0) + +extern uint32_t v3d_debug_flag_for_shader_stage(gl_shader_stage stage); + +extern void v3d_process_debug_variable(void); + +#ifdef __cplusplus +} +#endif + +#endif /* V3D_DEBUG_H */ diff --git a/lib/mesa/src/broadcom/compiler/nir_to_vir.c b/lib/mesa/src/broadcom/compiler/nir_to_vir.c new file mode 100644 index 000000000..3b032b704 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/nir_to_vir.c @@ -0,0 +1,2054 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <inttypes.h> +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/ralloc.h" +#include "util/hash_table.h" +#include "compiler/nir/nir.h" +#include "compiler/nir/nir_builder.h" +#include "v3d_compiler.h" + +/* We don't do any address packing. */ +#define __gen_user_data void +#define __gen_address_type uint32_t +#define __gen_address_offset(reloc) (*reloc) +#define __gen_emit_reloc(cl, reloc) +#include "cle/v3d_packet_v33_pack.h" + +static struct qreg +ntq_get_src(struct v3d_compile *c, nir_src src, int i); +static void +ntq_emit_cf_list(struct v3d_compile *c, struct exec_list *list); + +static void +resize_qreg_array(struct v3d_compile *c, + struct qreg **regs, + uint32_t *size, + uint32_t decl_size) +{ + if (*size >= decl_size) + return; + + uint32_t old_size = *size; + *size = MAX2(*size * 2, decl_size); + *regs = reralloc(c, *regs, struct qreg, *size); + if (!*regs) { + fprintf(stderr, "Malloc failure\n"); + abort(); + } + + for (uint32_t i = old_size; i < *size; i++) + (*regs)[i] = c->undef; +} + +static struct qreg +vir_SFU(struct v3d_compile *c, int waddr, struct qreg src) +{ + vir_FMOV_dest(c, vir_reg(QFILE_MAGIC, waddr), src); + return vir_FMOV(c, vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_R4)); +} + +static struct qreg +vir_LDTMU(struct v3d_compile *c) +{ + vir_NOP(c)->qpu.sig.ldtmu = true; + return vir_MOV(c, vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_R4)); +} + +static struct qreg +indirect_uniform_load(struct v3d_compile *c, nir_intrinsic_instr *intr) +{ + struct qreg indirect_offset = ntq_get_src(c, intr->src[0], 0); + uint32_t offset = nir_intrinsic_base(intr); + struct v3d_ubo_range *range = NULL; + unsigned i; + + for (i = 0; i < c->num_ubo_ranges; i++) { + range = &c->ubo_ranges[i]; + if (offset >= range->src_offset && + offset < range->src_offset + range->size) { + break; + } + } + /* The driver-location-based offset always has to be within a declared + * uniform range. + */ + assert(i != c->num_ubo_ranges); + if (!c->ubo_range_used[i]) { + c->ubo_range_used[i] = true; + range->dst_offset = c->next_ubo_dst_offset; + c->next_ubo_dst_offset += range->size; + } + + offset -= range->src_offset; + + if (range->dst_offset + offset != 0) { + indirect_offset = vir_ADD(c, indirect_offset, + vir_uniform_ui(c, range->dst_offset + + offset)); + } + + /* Adjust for where we stored the TGSI register base. */ + vir_ADD_dest(c, + vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_TMUA), + vir_uniform(c, QUNIFORM_UBO_ADDR, 0), + indirect_offset); + + return vir_LDTMU(c); +} + +static struct qreg * +ntq_init_ssa_def(struct v3d_compile *c, nir_ssa_def *def) +{ + struct qreg *qregs = ralloc_array(c->def_ht, struct qreg, + def->num_components); + _mesa_hash_table_insert(c->def_ht, def, qregs); + return qregs; +} + +/** + * This function is responsible for getting VIR results into the associated + * storage for a NIR instruction. + * + * If it's a NIR SSA def, then we just set the associated hash table entry to + * the new result. + * + * If it's a NIR reg, then we need to update the existing qreg assigned to the + * NIR destination with the incoming value. To do that without introducing + * new MOVs, we require that the incoming qreg either be a uniform, or be + * SSA-defined by the previous VIR instruction in the block and rewritable by + * this function. That lets us sneak ahead and insert the SF flag beforehand + * (knowing that the previous instruction doesn't depend on flags) and rewrite + * its destination to be the NIR reg's destination + */ +static void +ntq_store_dest(struct v3d_compile *c, nir_dest *dest, int chan, + struct qreg result) +{ + struct qinst *last_inst = NULL; + if (!list_empty(&c->cur_block->instructions)) + last_inst = (struct qinst *)c->cur_block->instructions.prev; + + assert(result.file == QFILE_UNIF || + (result.file == QFILE_TEMP && + last_inst && last_inst == c->defs[result.index])); + + if (dest->is_ssa) { + assert(chan < dest->ssa.num_components); + + struct qreg *qregs; + struct hash_entry *entry = + _mesa_hash_table_search(c->def_ht, &dest->ssa); + + if (entry) + qregs = entry->data; + else + qregs = ntq_init_ssa_def(c, &dest->ssa); + + qregs[chan] = result; + } else { + nir_register *reg = dest->reg.reg; + assert(dest->reg.base_offset == 0); + assert(reg->num_array_elems == 0); + struct hash_entry *entry = + _mesa_hash_table_search(c->def_ht, reg); + struct qreg *qregs = entry->data; + + /* Insert a MOV if the source wasn't an SSA def in the + * previous instruction. + */ + if (result.file == QFILE_UNIF) { + result = vir_MOV(c, result); + last_inst = c->defs[result.index]; + } + + /* We know they're both temps, so just rewrite index. */ + c->defs[last_inst->dst.index] = NULL; + last_inst->dst.index = qregs[chan].index; + + /* If we're in control flow, then make this update of the reg + * conditional on the execution mask. + */ + if (c->execute.file != QFILE_NULL) { + last_inst->dst.index = qregs[chan].index; + + /* Set the flags to the current exec mask. To insert + * the flags push, we temporarily remove our SSA + * instruction. + */ + list_del(&last_inst->link); + vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ); + list_addtail(&last_inst->link, + &c->cur_block->instructions); + + vir_set_cond(last_inst, V3D_QPU_COND_IFA); + last_inst->cond_is_exec_mask = true; + } + } +} + +static struct qreg +ntq_get_src(struct v3d_compile *c, nir_src src, int i) +{ + struct hash_entry *entry; + if (src.is_ssa) { + entry = _mesa_hash_table_search(c->def_ht, src.ssa); + assert(i < src.ssa->num_components); + } else { + nir_register *reg = src.reg.reg; + entry = _mesa_hash_table_search(c->def_ht, reg); + assert(reg->num_array_elems == 0); + assert(src.reg.base_offset == 0); + assert(i < reg->num_components); + } + + struct qreg *qregs = entry->data; + return qregs[i]; +} + +static struct qreg +ntq_get_alu_src(struct v3d_compile *c, nir_alu_instr *instr, + unsigned src) +{ + assert(util_is_power_of_two(instr->dest.write_mask)); + unsigned chan = ffs(instr->dest.write_mask) - 1; + struct qreg r = ntq_get_src(c, instr->src[src].src, + instr->src[src].swizzle[chan]); + + assert(!instr->src[src].abs); + assert(!instr->src[src].negate); + + return r; +}; + +static inline struct qreg +vir_SAT(struct v3d_compile *c, struct qreg val) +{ + return vir_FMAX(c, + vir_FMIN(c, val, vir_uniform_f(c, 1.0)), + vir_uniform_f(c, 0.0)); +} + +static struct qreg +ntq_umul(struct v3d_compile *c, struct qreg src0, struct qreg src1) +{ + vir_MULTOP(c, src0, src1); + return vir_UMUL24(c, src0, src1); +} + +static struct qreg +ntq_minify(struct v3d_compile *c, struct qreg size, struct qreg level) +{ + return vir_MAX(c, vir_SHR(c, size, level), vir_uniform_ui(c, 1)); +} + +static void +ntq_emit_txs(struct v3d_compile *c, nir_tex_instr *instr) +{ + unsigned unit = instr->texture_index; + int lod_index = nir_tex_instr_src_index(instr, nir_tex_src_lod); + int dest_size = nir_tex_instr_dest_size(instr); + + struct qreg lod = c->undef; + if (lod_index != -1) + lod = ntq_get_src(c, instr->src[lod_index].src, 0); + + for (int i = 0; i < dest_size; i++) { + assert(i < 3); + enum quniform_contents contents; + + if (instr->is_array && i == dest_size - 1) + contents = QUNIFORM_TEXTURE_ARRAY_SIZE; + else + contents = QUNIFORM_TEXTURE_WIDTH + i; + + struct qreg size = vir_uniform(c, contents, unit); + + switch (instr->sampler_dim) { + case GLSL_SAMPLER_DIM_1D: + case GLSL_SAMPLER_DIM_2D: + case GLSL_SAMPLER_DIM_3D: + case GLSL_SAMPLER_DIM_CUBE: + /* Don't minify the array size. */ + if (!(instr->is_array && i == dest_size - 1)) { + size = ntq_minify(c, size, lod); + } + break; + + case GLSL_SAMPLER_DIM_RECT: + /* There's no LOD field for rects */ + break; + + default: + unreachable("Bad sampler type"); + } + + ntq_store_dest(c, &instr->dest, i, size); + } +} + +static void +ntq_emit_tex(struct v3d_compile *c, nir_tex_instr *instr) +{ + unsigned unit = instr->texture_index; + + /* Since each texture sampling op requires uploading uniforms to + * reference the texture, there's no HW support for texture size and + * you just upload uniforms containing the size. + */ + switch (instr->op) { + case nir_texop_query_levels: + ntq_store_dest(c, &instr->dest, 0, + vir_uniform(c, QUNIFORM_TEXTURE_LEVELS, unit)); + return; + case nir_texop_txs: + ntq_emit_txs(c, instr); + return; + default: + break; + } + + struct V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1 p0_unpacked = { + V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_header, + + .fetch_sample_mode = instr->op == nir_texop_txf, + }; + + switch (instr->sampler_dim) { + case GLSL_SAMPLER_DIM_1D: + if (instr->is_array) + p0_unpacked.lookup_type = TEXTURE_1D_ARRAY; + else + p0_unpacked.lookup_type = TEXTURE_1D; + break; + case GLSL_SAMPLER_DIM_2D: + case GLSL_SAMPLER_DIM_RECT: + if (instr->is_array) + p0_unpacked.lookup_type = TEXTURE_2D_ARRAY; + else + p0_unpacked.lookup_type = TEXTURE_2D; + break; + case GLSL_SAMPLER_DIM_3D: + p0_unpacked.lookup_type = TEXTURE_3D; + break; + case GLSL_SAMPLER_DIM_CUBE: + p0_unpacked.lookup_type = TEXTURE_CUBE_MAP; + break; + default: + unreachable("Bad sampler type"); + } + + struct qreg coords[5]; + int next_coord = 0; + for (unsigned i = 0; i < instr->num_srcs; i++) { + switch (instr->src[i].src_type) { + case nir_tex_src_coord: + for (int j = 0; j < instr->coord_components; j++) { + coords[next_coord++] = + ntq_get_src(c, instr->src[i].src, j); + } + if (instr->coord_components < 2) + coords[next_coord++] = vir_uniform_f(c, 0.5); + break; + case nir_tex_src_bias: + coords[next_coord++] = + ntq_get_src(c, instr->src[i].src, 0); + + p0_unpacked.bias_supplied = true; + break; + case nir_tex_src_lod: + /* XXX: Needs base level addition */ + coords[next_coord++] = + ntq_get_src(c, instr->src[i].src, 0); + + if (instr->op != nir_texop_txf && + instr->op != nir_texop_tg4) { + p0_unpacked.disable_autolod_use_bias_only = true; + } + break; + case nir_tex_src_comparator: + coords[next_coord++] = + ntq_get_src(c, instr->src[i].src, 0); + + p0_unpacked.shadow = true; + break; + + case nir_tex_src_offset: { + nir_const_value *offset = + nir_src_as_const_value(instr->src[i].src); + p0_unpacked.texel_offset_for_s_coordinate = + offset->i32[0]; + + if (instr->coord_components >= 2) + p0_unpacked.texel_offset_for_t_coordinate = + offset->i32[1]; + + if (instr->coord_components >= 3) + p0_unpacked.texel_offset_for_r_coordinate = + offset->i32[2]; + break; + } + + default: + unreachable("unknown texture source"); + } + } + + uint32_t p0_packed; + V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_pack(NULL, + (uint8_t *)&p0_packed, + &p0_unpacked); + + /* There is no native support for GL texture rectangle coordinates, so + * we have to rescale from ([0, width], [0, height]) to ([0, 1], [0, + * 1]). + */ + if (instr->sampler_dim == GLSL_SAMPLER_DIM_RECT) { + coords[0] = vir_FMUL(c, coords[0], + vir_uniform(c, QUNIFORM_TEXRECT_SCALE_X, + unit)); + coords[1] = vir_FMUL(c, coords[1], + vir_uniform(c, QUNIFORM_TEXRECT_SCALE_Y, + unit)); + } + + struct qreg texture_u[] = { + vir_uniform(c, QUNIFORM_TEXTURE_CONFIG_P0_0 + unit, p0_packed), + vir_uniform(c, QUNIFORM_TEXTURE_CONFIG_P1, unit), + }; + uint32_t next_texture_u = 0; + + for (int i = 0; i < next_coord; i++) { + struct qreg dst; + + if (i == next_coord - 1) + dst = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_TMUL); + else + dst = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_TMU); + + struct qinst *tmu = vir_MOV_dest(c, dst, coords[i]); + + if (i < 2) { + tmu->has_implicit_uniform = true; + tmu->src[vir_get_implicit_uniform_src(tmu)] = + texture_u[next_texture_u++]; + } + } + + bool return_16 = (c->key->tex[unit].return_size == 16 || + p0_unpacked.shadow); + + struct qreg return_values[4]; + for (int i = 0; i < c->key->tex[unit].return_channels; i++) + return_values[i] = vir_LDTMU(c); + /* Swizzling .zw of an RG texture should give undefined results, not + * crash the compiler. + */ + for (int i = c->key->tex[unit].return_channels; i < 4; i++) + return_values[i] = c->undef; + + for (int i = 0; i < nir_tex_instr_dest_size(instr); i++) { + struct qreg chan; + + if (return_16) { + STATIC_ASSERT(PIPE_SWIZZLE_X == 0); + chan = return_values[i / 2]; + + enum v3d_qpu_input_unpack unpack; + if (i & 1) + unpack = V3D_QPU_UNPACK_H; + else + unpack = V3D_QPU_UNPACK_L; + + chan = vir_FMOV(c, chan); + vir_set_unpack(c->defs[chan.index], 0, unpack); + } else { + chan = vir_MOV(c, return_values[i]); + } + ntq_store_dest(c, &instr->dest, i, chan); + } +} + +static struct qreg +ntq_fsincos(struct v3d_compile *c, struct qreg src, bool is_cos) +{ + struct qreg input = vir_FMUL(c, src, vir_uniform_f(c, 1.0f / M_PI)); + if (is_cos) + input = vir_FADD(c, input, vir_uniform_f(c, 0.5)); + + struct qreg periods = vir_FROUND(c, input); + struct qreg sin_output = vir_SFU(c, V3D_QPU_WADDR_SIN, + vir_FSUB(c, input, periods)); + return vir_XOR(c, sin_output, vir_SHL(c, + vir_FTOIN(c, periods), + vir_uniform_ui(c, -1))); +} + +static struct qreg +ntq_fsign(struct v3d_compile *c, struct qreg src) +{ + struct qreg t = vir_get_temp(c); + + vir_MOV_dest(c, t, vir_uniform_f(c, 0.0)); + vir_PF(c, vir_FMOV(c, src), V3D_QPU_PF_PUSHZ); + vir_MOV_cond(c, V3D_QPU_COND_IFNA, t, vir_uniform_f(c, 1.0)); + vir_PF(c, vir_FMOV(c, src), V3D_QPU_PF_PUSHN); + vir_MOV_cond(c, V3D_QPU_COND_IFA, t, vir_uniform_f(c, -1.0)); + return vir_MOV(c, t); +} + +static struct qreg +ntq_isign(struct v3d_compile *c, struct qreg src) +{ + struct qreg t = vir_get_temp(c); + + vir_MOV_dest(c, t, vir_uniform_ui(c, 0)); + vir_PF(c, vir_MOV(c, src), V3D_QPU_PF_PUSHZ); + vir_MOV_cond(c, V3D_QPU_COND_IFNA, t, vir_uniform_ui(c, 1)); + vir_PF(c, vir_MOV(c, src), V3D_QPU_PF_PUSHN); + vir_MOV_cond(c, V3D_QPU_COND_IFA, t, vir_uniform_ui(c, -1)); + return vir_MOV(c, t); +} + +static void +emit_fragcoord_input(struct v3d_compile *c, int attr) +{ + c->inputs[attr * 4 + 0] = vir_FXCD(c); + c->inputs[attr * 4 + 1] = vir_FYCD(c); + c->inputs[attr * 4 + 2] = c->payload_z; + c->inputs[attr * 4 + 3] = vir_SFU(c, V3D_QPU_WADDR_RECIP, + c->payload_w); +} + +static struct qreg +emit_fragment_varying(struct v3d_compile *c, nir_variable *var, + uint8_t swizzle) +{ + struct qreg vary = vir_reg(QFILE_VARY, ~0); + struct qreg r5 = vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_R5); + + /* For gl_PointCoord input or distance along a line, we'll be called + * with no nir_variable, and we don't count toward VPM size so we + * don't track an input slot. + */ + if (!var) { + return vir_FADD(c, vir_FMUL(c, vary, c->payload_w), r5); + } + + int i = c->num_inputs++; + c->input_slots[i] = v3d_slot_from_slot_and_component(var->data.location, + swizzle); + + switch (var->data.interpolation) { + case INTERP_MODE_NONE: + /* If a gl_FrontColor or gl_BackColor input has no interp + * qualifier, then flag it for glShadeModel() handling by the + * driver. + */ + switch (var->data.location) { + case VARYING_SLOT_COL0: + case VARYING_SLOT_COL1: + case VARYING_SLOT_BFC0: + case VARYING_SLOT_BFC1: + BITSET_SET(c->shade_model_flags, i); + break; + default: + break; + } + /* FALLTHROUGH */ + case INTERP_MODE_SMOOTH: + if (var->data.centroid) { + return vir_FADD(c, vir_FMUL(c, vary, + c->payload_w_centroid), r5); + } else { + return vir_FADD(c, vir_FMUL(c, vary, c->payload_w), r5); + } + case INTERP_MODE_NOPERSPECTIVE: + /* C appears after the mov from the varying. + XXX: improve ldvary setup. + */ + return vir_FADD(c, vir_MOV(c, vary), r5); + case INTERP_MODE_FLAT: + BITSET_SET(c->flat_shade_flags, i); + vir_MOV_dest(c, c->undef, vary); + return vir_MOV(c, r5); + default: + unreachable("Bad interp mode"); + } +} + +static void +emit_fragment_input(struct v3d_compile *c, int attr, nir_variable *var) +{ + for (int i = 0; i < glsl_get_vector_elements(var->type); i++) { + c->inputs[attr * 4 + i] = + emit_fragment_varying(c, var, i); + } +} + +static void +add_output(struct v3d_compile *c, + uint32_t decl_offset, + uint8_t slot, + uint8_t swizzle) +{ + uint32_t old_array_size = c->outputs_array_size; + resize_qreg_array(c, &c->outputs, &c->outputs_array_size, + decl_offset + 1); + + if (old_array_size != c->outputs_array_size) { + c->output_slots = reralloc(c, + c->output_slots, + struct v3d_varying_slot, + c->outputs_array_size); + } + + c->output_slots[decl_offset] = + v3d_slot_from_slot_and_component(slot, swizzle); +} + +static void +declare_uniform_range(struct v3d_compile *c, uint32_t start, uint32_t size) +{ + unsigned array_id = c->num_ubo_ranges++; + if (array_id >= c->ubo_ranges_array_size) { + c->ubo_ranges_array_size = MAX2(c->ubo_ranges_array_size * 2, + array_id + 1); + c->ubo_ranges = reralloc(c, c->ubo_ranges, + struct v3d_ubo_range, + c->ubo_ranges_array_size); + c->ubo_range_used = reralloc(c, c->ubo_range_used, + bool, + c->ubo_ranges_array_size); + } + + c->ubo_ranges[array_id].dst_offset = 0; + c->ubo_ranges[array_id].src_offset = start; + c->ubo_ranges[array_id].size = size; + c->ubo_range_used[array_id] = false; +} + +/** + * If compare_instr is a valid comparison instruction, emits the + * compare_instr's comparison and returns the sel_instr's return value based + * on the compare_instr's result. + */ +static bool +ntq_emit_comparison(struct v3d_compile *c, struct qreg *dest, + nir_alu_instr *compare_instr, + nir_alu_instr *sel_instr) +{ + struct qreg src0 = ntq_get_alu_src(c, compare_instr, 0); + struct qreg src1 = ntq_get_alu_src(c, compare_instr, 1); + bool cond_invert = false; + + switch (compare_instr->op) { + case nir_op_feq: + case nir_op_seq: + vir_PF(c, vir_FCMP(c, src0, src1), V3D_QPU_PF_PUSHZ); + break; + case nir_op_ieq: + vir_PF(c, vir_XOR(c, src0, src1), V3D_QPU_PF_PUSHZ); + break; + + case nir_op_fne: + case nir_op_sne: + vir_PF(c, vir_FCMP(c, src0, src1), V3D_QPU_PF_PUSHZ); + cond_invert = true; + break; + case nir_op_ine: + vir_PF(c, vir_XOR(c, src0, src1), V3D_QPU_PF_PUSHZ); + cond_invert = true; + break; + + case nir_op_fge: + case nir_op_sge: + vir_PF(c, vir_FCMP(c, src1, src0), V3D_QPU_PF_PUSHC); + break; + case nir_op_ige: + vir_PF(c, vir_MIN(c, src1, src0), V3D_QPU_PF_PUSHC); + cond_invert = true; + break; + case nir_op_uge: + vir_PF(c, vir_SUB(c, src0, src1), V3D_QPU_PF_PUSHC); + cond_invert = true; + break; + + case nir_op_slt: + case nir_op_flt: + vir_PF(c, vir_FCMP(c, src0, src1), V3D_QPU_PF_PUSHN); + break; + case nir_op_ilt: + vir_PF(c, vir_MIN(c, src1, src0), V3D_QPU_PF_PUSHC); + break; + case nir_op_ult: + vir_PF(c, vir_SUB(c, src0, src1), V3D_QPU_PF_PUSHC); + break; + + default: + return false; + } + + enum v3d_qpu_cond cond = (cond_invert ? + V3D_QPU_COND_IFNA : + V3D_QPU_COND_IFA); + + switch (sel_instr->op) { + case nir_op_seq: + case nir_op_sne: + case nir_op_sge: + case nir_op_slt: + *dest = vir_SEL(c, cond, + vir_uniform_f(c, 1.0), vir_uniform_f(c, 0.0)); + break; + + case nir_op_bcsel: + *dest = vir_SEL(c, cond, + ntq_get_alu_src(c, sel_instr, 1), + ntq_get_alu_src(c, sel_instr, 2)); + break; + + default: + *dest = vir_SEL(c, cond, + vir_uniform_ui(c, ~0), vir_uniform_ui(c, 0)); + break; + } + + /* Make the temporary for nir_store_dest(). */ + *dest = vir_MOV(c, *dest); + + return true; +} + +/** + * Attempts to fold a comparison generating a boolean result into the + * condition code for selecting between two values, instead of comparing the + * boolean result against 0 to generate the condition code. + */ +static struct qreg ntq_emit_bcsel(struct v3d_compile *c, nir_alu_instr *instr, + struct qreg *src) +{ + if (!instr->src[0].src.is_ssa) + goto out; + if (instr->src[0].src.ssa->parent_instr->type != nir_instr_type_alu) + goto out; + nir_alu_instr *compare = + nir_instr_as_alu(instr->src[0].src.ssa->parent_instr); + if (!compare) + goto out; + + struct qreg dest; + if (ntq_emit_comparison(c, &dest, compare, instr)) + return dest; + +out: + vir_PF(c, src[0], V3D_QPU_PF_PUSHZ); + return vir_MOV(c, vir_SEL(c, V3D_QPU_COND_IFNA, src[1], src[2])); +} + + +static void +ntq_emit_alu(struct v3d_compile *c, nir_alu_instr *instr) +{ + /* This should always be lowered to ALU operations for V3D. */ + assert(!instr->dest.saturate); + + /* Vectors are special in that they have non-scalarized writemasks, + * and just take the first swizzle channel for each argument in order + * into each writemask channel. + */ + if (instr->op == nir_op_vec2 || + instr->op == nir_op_vec3 || + instr->op == nir_op_vec4) { + struct qreg srcs[4]; + for (int i = 0; i < nir_op_infos[instr->op].num_inputs; i++) + srcs[i] = ntq_get_src(c, instr->src[i].src, + instr->src[i].swizzle[0]); + for (int i = 0; i < nir_op_infos[instr->op].num_inputs; i++) + ntq_store_dest(c, &instr->dest.dest, i, + vir_MOV(c, srcs[i])); + return; + } + + /* General case: We can just grab the one used channel per src. */ + struct qreg src[nir_op_infos[instr->op].num_inputs]; + for (int i = 0; i < nir_op_infos[instr->op].num_inputs; i++) { + src[i] = ntq_get_alu_src(c, instr, i); + } + + struct qreg result; + + switch (instr->op) { + case nir_op_fmov: + case nir_op_imov: + result = vir_MOV(c, src[0]); + break; + case nir_op_fmul: + result = vir_FMUL(c, src[0], src[1]); + break; + case nir_op_fadd: + result = vir_FADD(c, src[0], src[1]); + break; + case nir_op_fsub: + result = vir_FSUB(c, src[0], src[1]); + break; + case nir_op_fmin: + result = vir_FMIN(c, src[0], src[1]); + break; + case nir_op_fmax: + result = vir_FMAX(c, src[0], src[1]); + break; + + case nir_op_f2i32: + result = vir_FTOIZ(c, src[0]); + break; + case nir_op_f2u32: + result = vir_FTOUZ(c, src[0]); + break; + case nir_op_i2f32: + result = vir_ITOF(c, src[0]); + break; + case nir_op_u2f32: + result = vir_UTOF(c, src[0]); + break; + case nir_op_b2f: + result = vir_AND(c, src[0], vir_uniform_f(c, 1.0)); + break; + case nir_op_b2i: + result = vir_AND(c, src[0], vir_uniform_ui(c, 1)); + break; + case nir_op_i2b: + case nir_op_f2b: + vir_PF(c, src[0], V3D_QPU_PF_PUSHZ); + result = vir_MOV(c, vir_SEL(c, V3D_QPU_COND_IFNA, + vir_uniform_ui(c, ~0), + vir_uniform_ui(c, 0))); + break; + + case nir_op_iadd: + result = vir_ADD(c, src[0], src[1]); + break; + case nir_op_ushr: + result = vir_SHR(c, src[0], src[1]); + break; + case nir_op_isub: + result = vir_SUB(c, src[0], src[1]); + break; + case nir_op_ishr: + result = vir_ASR(c, src[0], src[1]); + break; + case nir_op_ishl: + result = vir_SHL(c, src[0], src[1]); + break; + case nir_op_imin: + result = vir_MIN(c, src[0], src[1]); + break; + case nir_op_umin: + result = vir_UMIN(c, src[0], src[1]); + break; + case nir_op_imax: + result = vir_MAX(c, src[0], src[1]); + break; + case nir_op_umax: + result = vir_UMAX(c, src[0], src[1]); + break; + case nir_op_iand: + result = vir_AND(c, src[0], src[1]); + break; + case nir_op_ior: + result = vir_OR(c, src[0], src[1]); + break; + case nir_op_ixor: + result = vir_XOR(c, src[0], src[1]); + break; + case nir_op_inot: + result = vir_NOT(c, src[0]); + break; + + case nir_op_imul: + result = ntq_umul(c, src[0], src[1]); + break; + + case nir_op_seq: + case nir_op_sne: + case nir_op_sge: + case nir_op_slt: + case nir_op_feq: + case nir_op_fne: + case nir_op_fge: + case nir_op_flt: + case nir_op_ieq: + case nir_op_ine: + case nir_op_ige: + case nir_op_uge: + case nir_op_ilt: + case nir_op_ult: + if (!ntq_emit_comparison(c, &result, instr, instr)) { + fprintf(stderr, "Bad comparison instruction\n"); + } + break; + + case nir_op_bcsel: + result = ntq_emit_bcsel(c, instr, src); + break; + case nir_op_fcsel: + vir_PF(c, src[0], V3D_QPU_PF_PUSHZ); + result = vir_MOV(c, vir_SEL(c, V3D_QPU_COND_IFNA, + src[1], src[2])); + break; + + case nir_op_frcp: + result = vir_SFU(c, V3D_QPU_WADDR_RECIP, src[0]); + break; + case nir_op_frsq: + result = vir_SFU(c, V3D_QPU_WADDR_RSQRT, src[0]); + break; + case nir_op_fexp2: + result = vir_SFU(c, V3D_QPU_WADDR_EXP, src[0]); + break; + case nir_op_flog2: + result = vir_SFU(c, V3D_QPU_WADDR_LOG, src[0]); + break; + + case nir_op_fceil: + result = vir_FCEIL(c, src[0]); + break; + case nir_op_ffloor: + result = vir_FFLOOR(c, src[0]); + break; + case nir_op_fround_even: + result = vir_FROUND(c, src[0]); + break; + case nir_op_ftrunc: + result = vir_FTRUNC(c, src[0]); + break; + case nir_op_ffract: + result = vir_FSUB(c, src[0], vir_FFLOOR(c, src[0])); + break; + + case nir_op_fsin: + result = ntq_fsincos(c, src[0], false); + break; + case nir_op_fcos: + result = ntq_fsincos(c, src[0], true); + break; + + case nir_op_fsign: + result = ntq_fsign(c, src[0]); + break; + case nir_op_isign: + result = ntq_isign(c, src[0]); + break; + + case nir_op_fabs: { + result = vir_FMOV(c, src[0]); + vir_set_unpack(c->defs[result.index], 0, V3D_QPU_UNPACK_ABS); + break; + } + + case nir_op_iabs: + result = vir_MAX(c, src[0], + vir_SUB(c, vir_uniform_ui(c, 0), src[0])); + break; + + case nir_op_fddx: + case nir_op_fddx_coarse: + case nir_op_fddx_fine: + result = vir_FDX(c, src[0]); + break; + + case nir_op_fddy: + case nir_op_fddy_coarse: + case nir_op_fddy_fine: + result = vir_FDY(c, src[0]); + break; + + default: + fprintf(stderr, "unknown NIR ALU inst: "); + nir_print_instr(&instr->instr, stderr); + fprintf(stderr, "\n"); + abort(); + } + + /* We have a scalar result, so the instruction should only have a + * single channel written to. + */ + assert(util_is_power_of_two(instr->dest.write_mask)); + ntq_store_dest(c, &instr->dest.dest, + ffs(instr->dest.write_mask) - 1, result); +} + +/* Each TLB read/write setup (a render target or depth buffer) takes an 8-bit + * specifier. They come from a register that's preloaded with 0xffffffff + * (0xff gets you normal vec4 f16 RT0 writes), and when one is neaded the low + * 8 bits are shifted off the bottom and 0xff shifted in from the top. + */ +#define TLB_TYPE_F16_COLOR (3 << 6) +#define TLB_TYPE_I32_COLOR (1 << 6) +#define TLB_TYPE_F32_COLOR (0 << 6) +#define TLB_RENDER_TARGET_SHIFT 3 /* Reversed! 7 = RT 0, 0 = RT 7. */ +#define TLB_SAMPLE_MODE_PER_SAMPLE (0 << 2) +#define TLB_SAMPLE_MODE_PER_PIXEL (1 << 2) +#define TLB_F16_SWAP_HI_LO (1 << 1) +#define TLB_VEC_SIZE_4_F16 (1 << 0) +#define TLB_VEC_SIZE_2_F16 (0 << 0) +#define TLB_VEC_SIZE_MINUS_1_SHIFT 0 + +/* Triggers Z/Stencil testing, used when the shader state's "FS modifies Z" + * flag is set. + */ +#define TLB_TYPE_DEPTH ((2 << 6) | (0 << 4)) +#define TLB_DEPTH_TYPE_INVARIANT (0 << 2) /* Unmodified sideband input used */ +#define TLB_DEPTH_TYPE_PER_PIXEL (1 << 2) /* QPU result used */ + +/* Stencil is a single 32-bit write. */ +#define TLB_TYPE_STENCIL_ALPHA ((2 << 6) | (1 << 4)) + +static void +emit_frag_end(struct v3d_compile *c) +{ + /* XXX + if (c->output_sample_mask_index != -1) { + vir_MS_MASK(c, c->outputs[c->output_sample_mask_index]); + } + */ + + if (c->output_position_index != -1) { + struct qinst *inst = vir_MOV_dest(c, + vir_reg(QFILE_TLBU, 0), + c->outputs[c->output_position_index]); + + inst->src[vir_get_implicit_uniform_src(inst)] = + vir_uniform_ui(c, + TLB_TYPE_DEPTH | + TLB_DEPTH_TYPE_PER_PIXEL | + 0xffffff00); + } else if (c->s->info.fs.uses_discard) { + struct qinst *inst = vir_MOV_dest(c, + vir_reg(QFILE_TLBU, 0), + vir_reg(QFILE_NULL, 0)); + + inst->src[vir_get_implicit_uniform_src(inst)] = + vir_uniform_ui(c, + TLB_TYPE_DEPTH | + TLB_DEPTH_TYPE_INVARIANT | + 0xffffff00); + } + + /* XXX: Performance improvement: Merge Z write and color writes TLB + * uniform setup + */ + + for (int rt = 0; rt < c->fs_key->nr_cbufs; rt++) { + if (!c->output_color_var[rt]) + continue; + + nir_variable *var = c->output_color_var[rt]; + struct qreg *color = &c->outputs[var->data.driver_location * 4]; + int num_components = glsl_get_vector_elements(var->type); + uint32_t conf = 0xffffff00; + struct qinst *inst; + + conf |= TLB_SAMPLE_MODE_PER_PIXEL; + conf |= (7 - rt) << TLB_RENDER_TARGET_SHIFT; + + assert(num_components != 0); + switch (glsl_get_base_type(var->type)) { + case GLSL_TYPE_UINT: + case GLSL_TYPE_INT: + conf |= TLB_TYPE_I32_COLOR; + conf |= ((num_components - 1) << + TLB_VEC_SIZE_MINUS_1_SHIFT); + + inst = vir_MOV_dest(c, vir_reg(QFILE_TLBU, 0), color[0]); + inst->src[vir_get_implicit_uniform_src(inst)] = + vir_uniform_ui(c, conf); + + for (int i = 1; i < num_components; i++) { + inst = vir_MOV_dest(c, vir_reg(QFILE_TLB, 0), + color[i]); + } + break; + + default: { + struct qreg r = color[0]; + struct qreg g = color[1]; + struct qreg b = color[2]; + struct qreg a = color[3]; + + if (c->fs_key->f32_color_rb) { + conf |= TLB_TYPE_F32_COLOR; + conf |= ((num_components - 1) << + TLB_VEC_SIZE_MINUS_1_SHIFT); + } else { + conf |= TLB_TYPE_F16_COLOR; + conf |= TLB_F16_SWAP_HI_LO; + if (num_components >= 3) + conf |= TLB_VEC_SIZE_4_F16; + else + conf |= TLB_VEC_SIZE_2_F16; + } + + if (c->fs_key->swap_color_rb & (1 << rt)) { + r = color[2]; + b = color[0]; + } + + if (c->fs_key->f32_color_rb & (1 << rt)) { + inst = vir_MOV_dest(c, vir_reg(QFILE_TLBU, 0), color[0]); + inst->src[vir_get_implicit_uniform_src(inst)] = + vir_uniform_ui(c, conf); + + for (int i = 1; i < num_components; i++) { + inst = vir_MOV_dest(c, vir_reg(QFILE_TLB, 0), + color[i]); + } + } else { + inst = vir_VFPACK_dest(c, vir_reg(QFILE_TLB, 0), r, g); + if (conf != ~0) { + inst->dst.file = QFILE_TLBU; + inst->src[vir_get_implicit_uniform_src(inst)] = + vir_uniform_ui(c, conf); + } + + inst = vir_VFPACK_dest(c, vir_reg(QFILE_TLB, 0), b, a); + } + break; + } + } + } +} + +static void +emit_scaled_viewport_write(struct v3d_compile *c, struct qreg rcp_w) +{ + for (int i = 0; i < 2; i++) { + struct qreg coord = c->outputs[c->output_position_index + i]; + coord = vir_FMUL(c, coord, + vir_uniform(c, QUNIFORM_VIEWPORT_X_SCALE + i, + 0)); + coord = vir_FMUL(c, coord, rcp_w); + vir_FTOIN_dest(c, vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_VPM), + coord); + } + +} + +static void +emit_zs_write(struct v3d_compile *c, struct qreg rcp_w) +{ + struct qreg zscale = vir_uniform(c, QUNIFORM_VIEWPORT_Z_SCALE, 0); + struct qreg zoffset = vir_uniform(c, QUNIFORM_VIEWPORT_Z_OFFSET, 0); + + vir_FADD_dest(c, vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_VPM), + vir_FMUL(c, vir_FMUL(c, + c->outputs[c->output_position_index + 2], + zscale), + rcp_w), + zoffset); +} + +static void +emit_rcp_wc_write(struct v3d_compile *c, struct qreg rcp_w) +{ + vir_VPM_WRITE(c, rcp_w); +} + +static void +emit_point_size_write(struct v3d_compile *c) +{ + struct qreg point_size; + + if (c->output_point_size_index != -1) + point_size = c->outputs[c->output_point_size_index]; + else + point_size = vir_uniform_f(c, 1.0); + + /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835, + * BCM21553). + */ + point_size = vir_FMAX(c, point_size, vir_uniform_f(c, .125)); + + vir_VPM_WRITE(c, point_size); +} + +static void +emit_vpm_write_setup(struct v3d_compile *c) +{ + uint32_t packed; + struct V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP unpacked = { + V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP_header, + + .horiz = true, + .laned = false, + .segs = true, + .stride = 1, + .size = VPM_SETUP_SIZE_32_BIT, + .addr = 0, + }; + + V3D33_VPM_GENERIC_BLOCK_WRITE_SETUP_pack(NULL, + (uint8_t *)&packed, + &unpacked); + vir_VPMSETUP(c, vir_uniform_ui(c, packed)); +} + +static void +emit_vert_end(struct v3d_compile *c) +{ + struct qreg rcp_w = vir_SFU(c, V3D_QPU_WADDR_RECIP, + c->outputs[c->output_position_index + 3]); + + emit_vpm_write_setup(c); + + if (c->vs_key->is_coord) { + for (int i = 0; i < 4; i++) + vir_VPM_WRITE(c, c->outputs[c->output_position_index + i]); + emit_scaled_viewport_write(c, rcp_w); + if (c->vs_key->per_vertex_point_size) { + emit_point_size_write(c); + /* emit_rcp_wc_write(c, rcp_w); */ + } + /* XXX: Z-only rendering */ + if (0) + emit_zs_write(c, rcp_w); + } else { + emit_scaled_viewport_write(c, rcp_w); + emit_zs_write(c, rcp_w); + emit_rcp_wc_write(c, rcp_w); + if (c->vs_key->per_vertex_point_size) + emit_point_size_write(c); + } + + for (int i = 0; i < c->vs_key->num_fs_inputs; i++) { + struct v3d_varying_slot input = c->vs_key->fs_inputs[i]; + int j; + + for (j = 0; j < c->num_outputs; j++) { + struct v3d_varying_slot output = c->output_slots[j]; + + if (!memcmp(&input, &output, sizeof(input))) { + vir_VPM_WRITE(c, c->outputs[j]); + break; + } + } + /* Emit padding if we didn't find a declared VS output for + * this FS input. + */ + if (j == c->num_outputs) + vir_VPM_WRITE(c, vir_uniform_f(c, 0.0)); + } +} + +void +v3d_optimize_nir(struct nir_shader *s) +{ + bool progress; + + do { + progress = false; + + NIR_PASS_V(s, nir_lower_vars_to_ssa); + NIR_PASS(progress, s, nir_lower_alu_to_scalar); + NIR_PASS(progress, s, nir_lower_phis_to_scalar); + NIR_PASS(progress, s, nir_copy_prop); + NIR_PASS(progress, s, nir_opt_remove_phis); + NIR_PASS(progress, s, nir_opt_dce); + NIR_PASS(progress, s, nir_opt_dead_cf); + NIR_PASS(progress, s, nir_opt_cse); + NIR_PASS(progress, s, nir_opt_peephole_select, 8); + NIR_PASS(progress, s, nir_opt_algebraic); + NIR_PASS(progress, s, nir_opt_constant_folding); + NIR_PASS(progress, s, nir_opt_undef); + } while (progress); +} + +static int +driver_location_compare(const void *in_a, const void *in_b) +{ + const nir_variable *const *a = in_a; + const nir_variable *const *b = in_b; + + return (*a)->data.driver_location - (*b)->data.driver_location; +} + +static struct qreg +ntq_emit_vpm_read(struct v3d_compile *c, + uint32_t *num_components_queued, + uint32_t *remaining, + uint32_t vpm_index) +{ + struct qreg vpm = vir_reg(QFILE_VPM, vpm_index); + + if (*num_components_queued != 0) { + (*num_components_queued)--; + c->num_inputs++; + return vir_MOV(c, vpm); + } + + uint32_t num_components = MIN2(*remaining, 32); + + struct V3D33_VPM_GENERIC_BLOCK_READ_SETUP unpacked = { + V3D33_VPM_GENERIC_BLOCK_READ_SETUP_header, + + .horiz = true, + .laned = false, + /* If the field is 0, that means a read count of 32. */ + .num = num_components & 31, + .segs = true, + .stride = 1, + .size = VPM_SETUP_SIZE_32_BIT, + .addr = c->num_inputs, + }; + + uint32_t packed; + V3D33_VPM_GENERIC_BLOCK_READ_SETUP_pack(NULL, + (uint8_t *)&packed, + &unpacked); + vir_VPMSETUP(c, vir_uniform_ui(c, packed)); + + *num_components_queued = num_components - 1; + *remaining -= num_components; + c->num_inputs++; + + return vir_MOV(c, vpm); +} + +static void +ntq_setup_inputs(struct v3d_compile *c) +{ + unsigned num_entries = 0; + unsigned num_components = 0; + nir_foreach_variable(var, &c->s->inputs) { + num_entries++; + num_components += glsl_get_components(var->type); + } + + nir_variable *vars[num_entries]; + + unsigned i = 0; + nir_foreach_variable(var, &c->s->inputs) + vars[i++] = var; + + /* Sort the variables so that we emit the input setup in + * driver_location order. This is required for VPM reads, whose data + * is fetched into the VPM in driver_location (TGSI register index) + * order. + */ + qsort(&vars, num_entries, sizeof(*vars), driver_location_compare); + + uint32_t vpm_components_queued = 0; + if (c->s->info.stage == MESA_SHADER_VERTEX) { + bool uses_iid = c->s->info.system_values_read & + (1ull << SYSTEM_VALUE_INSTANCE_ID); + bool uses_vid = c->s->info.system_values_read & + (1ull << SYSTEM_VALUE_VERTEX_ID); + + num_components += uses_iid; + num_components += uses_vid; + + if (uses_iid) { + c->iid = ntq_emit_vpm_read(c, &vpm_components_queued, + &num_components, ~0); + } + + if (uses_vid) { + c->vid = ntq_emit_vpm_read(c, &vpm_components_queued, + &num_components, ~0); + } + } + + for (unsigned i = 0; i < num_entries; i++) { + nir_variable *var = vars[i]; + unsigned array_len = MAX2(glsl_get_length(var->type), 1); + unsigned loc = var->data.driver_location; + + assert(array_len == 1); + (void)array_len; + resize_qreg_array(c, &c->inputs, &c->inputs_array_size, + (loc + 1) * 4); + + if (c->s->info.stage == MESA_SHADER_FRAGMENT) { + if (var->data.location == VARYING_SLOT_POS) { + emit_fragcoord_input(c, loc); + } else if (var->data.location == VARYING_SLOT_PNTC || + (var->data.location >= VARYING_SLOT_VAR0 && + (c->fs_key->point_sprite_mask & + (1 << (var->data.location - + VARYING_SLOT_VAR0))))) { + c->inputs[loc * 4 + 0] = c->point_x; + c->inputs[loc * 4 + 1] = c->point_y; + } else { + emit_fragment_input(c, loc, var); + } + } else { + int var_components = glsl_get_components(var->type); + + for (int i = 0; i < var_components; i++) { + c->inputs[loc * 4 + i] = + ntq_emit_vpm_read(c, + &vpm_components_queued, + &num_components, + loc * 4 + i); + + } + c->vattr_sizes[loc] = var_components; + } + } + + if (c->s->info.stage == MESA_SHADER_VERTEX) { + assert(vpm_components_queued == 0); + assert(num_components == 0); + } +} + +static void +ntq_setup_outputs(struct v3d_compile *c) +{ + nir_foreach_variable(var, &c->s->outputs) { + unsigned array_len = MAX2(glsl_get_length(var->type), 1); + unsigned loc = var->data.driver_location * 4; + + assert(array_len == 1); + (void)array_len; + + for (int i = 0; i < 4; i++) + add_output(c, loc + i, var->data.location, i); + + if (c->s->info.stage == MESA_SHADER_FRAGMENT) { + switch (var->data.location) { + case FRAG_RESULT_COLOR: + c->output_color_var[0] = var; + c->output_color_var[1] = var; + c->output_color_var[2] = var; + c->output_color_var[3] = var; + break; + case FRAG_RESULT_DATA0: + case FRAG_RESULT_DATA1: + case FRAG_RESULT_DATA2: + case FRAG_RESULT_DATA3: + c->output_color_var[var->data.location - + FRAG_RESULT_DATA0] = var; + break; + case FRAG_RESULT_DEPTH: + c->output_position_index = loc; + break; + case FRAG_RESULT_SAMPLE_MASK: + c->output_sample_mask_index = loc; + break; + } + } else { + switch (var->data.location) { + case VARYING_SLOT_POS: + c->output_position_index = loc; + break; + case VARYING_SLOT_PSIZ: + c->output_point_size_index = loc; + break; + } + } + } +} + +static void +ntq_setup_uniforms(struct v3d_compile *c) +{ + nir_foreach_variable(var, &c->s->uniforms) { + uint32_t vec4_count = glsl_count_attribute_slots(var->type, + false); + unsigned vec4_size = 4 * sizeof(float); + + declare_uniform_range(c, var->data.driver_location * vec4_size, + vec4_count * vec4_size); + + } +} + +/** + * Sets up the mapping from nir_register to struct qreg *. + * + * Each nir_register gets a struct qreg per 32-bit component being stored. + */ +static void +ntq_setup_registers(struct v3d_compile *c, struct exec_list *list) +{ + foreach_list_typed(nir_register, nir_reg, node, list) { + unsigned array_len = MAX2(nir_reg->num_array_elems, 1); + struct qreg *qregs = ralloc_array(c->def_ht, struct qreg, + array_len * + nir_reg->num_components); + + _mesa_hash_table_insert(c->def_ht, nir_reg, qregs); + + for (int i = 0; i < array_len * nir_reg->num_components; i++) + qregs[i] = vir_get_temp(c); + } +} + +static void +ntq_emit_load_const(struct v3d_compile *c, nir_load_const_instr *instr) +{ + struct qreg *qregs = ntq_init_ssa_def(c, &instr->def); + for (int i = 0; i < instr->def.num_components; i++) + qregs[i] = vir_uniform_ui(c, instr->value.u32[i]); + + _mesa_hash_table_insert(c->def_ht, &instr->def, qregs); +} + +static void +ntq_emit_ssa_undef(struct v3d_compile *c, nir_ssa_undef_instr *instr) +{ + struct qreg *qregs = ntq_init_ssa_def(c, &instr->def); + + /* VIR needs there to be *some* value, so pick 0 (same as for + * ntq_setup_registers(). + */ + for (int i = 0; i < instr->def.num_components; i++) + qregs[i] = vir_uniform_ui(c, 0); +} + +static void +ntq_emit_intrinsic(struct v3d_compile *c, nir_intrinsic_instr *instr) +{ + nir_const_value *const_offset; + unsigned offset; + + switch (instr->intrinsic) { + case nir_intrinsic_load_uniform: + assert(instr->num_components == 1); + const_offset = nir_src_as_const_value(instr->src[0]); + if (const_offset) { + offset = nir_intrinsic_base(instr) + const_offset->u32[0]; + assert(offset % 4 == 0); + /* We need dwords */ + offset = offset / 4; + ntq_store_dest(c, &instr->dest, 0, + vir_uniform(c, QUNIFORM_UNIFORM, + offset)); + } else { + ntq_store_dest(c, &instr->dest, 0, + indirect_uniform_load(c, instr)); + } + break; + + case nir_intrinsic_load_ubo: + for (int i = 0; i < instr->num_components; i++) { + int ubo = nir_src_as_const_value(instr->src[0])->u32[0]; + + /* Adjust for where we stored the TGSI register base. */ + vir_ADD_dest(c, + vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_TMUA), + vir_uniform(c, QUNIFORM_UBO_ADDR, 1 + ubo), + vir_ADD(c, + ntq_get_src(c, instr->src[1], 0), + vir_uniform_ui(c, i * 4))); + + ntq_store_dest(c, &instr->dest, i, vir_LDTMU(c)); + } + break; + + const_offset = nir_src_as_const_value(instr->src[0]); + if (const_offset) { + offset = nir_intrinsic_base(instr) + const_offset->u32[0]; + assert(offset % 4 == 0); + /* We need dwords */ + offset = offset / 4; + ntq_store_dest(c, &instr->dest, 0, + vir_uniform(c, QUNIFORM_UNIFORM, + offset)); + } else { + ntq_store_dest(c, &instr->dest, 0, + indirect_uniform_load(c, instr)); + } + break; + + case nir_intrinsic_load_user_clip_plane: + for (int i = 0; i < instr->num_components; i++) { + ntq_store_dest(c, &instr->dest, i, + vir_uniform(c, QUNIFORM_USER_CLIP_PLANE, + nir_intrinsic_ucp_id(instr) * + 4 + i)); + } + break; + + case nir_intrinsic_load_alpha_ref_float: + ntq_store_dest(c, &instr->dest, 0, + vir_uniform(c, QUNIFORM_ALPHA_REF, 0)); + break; + + case nir_intrinsic_load_sample_mask_in: + ntq_store_dest(c, &instr->dest, 0, + vir_uniform(c, QUNIFORM_SAMPLE_MASK, 0)); + break; + + case nir_intrinsic_load_front_face: + /* The register contains 0 (front) or 1 (back), and we need to + * turn it into a NIR bool where true means front. + */ + ntq_store_dest(c, &instr->dest, 0, + vir_ADD(c, + vir_uniform_ui(c, -1), + vir_REVF(c))); + break; + + case nir_intrinsic_load_instance_id: + ntq_store_dest(c, &instr->dest, 0, vir_MOV(c, c->iid)); + break; + + case nir_intrinsic_load_vertex_id: + ntq_store_dest(c, &instr->dest, 0, vir_MOV(c, c->vid)); + break; + + case nir_intrinsic_load_input: + const_offset = nir_src_as_const_value(instr->src[0]); + assert(const_offset && "v3d doesn't support indirect inputs"); + for (int i = 0; i < instr->num_components; i++) { + offset = nir_intrinsic_base(instr) + const_offset->u32[0]; + int comp = nir_intrinsic_component(instr) + i; + ntq_store_dest(c, &instr->dest, i, + vir_MOV(c, c->inputs[offset * 4 + comp])); + } + break; + + case nir_intrinsic_store_output: + const_offset = nir_src_as_const_value(instr->src[1]); + assert(const_offset && "v3d doesn't support indirect outputs"); + offset = ((nir_intrinsic_base(instr) + + const_offset->u32[0]) * 4 + + nir_intrinsic_component(instr)); + + for (int i = 0; i < instr->num_components; i++) { + c->outputs[offset + i] = + vir_MOV(c, ntq_get_src(c, instr->src[0], i)); + } + c->num_outputs = MAX2(c->num_outputs, + offset + instr->num_components); + break; + + case nir_intrinsic_discard: + if (c->execute.file != QFILE_NULL) { + vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ); + vir_set_cond(vir_SETMSF_dest(c, vir_reg(QFILE_NULL, 0), + vir_uniform_ui(c, 0)), + V3D_QPU_COND_IFA); + } else { + vir_SETMSF_dest(c, vir_reg(QFILE_NULL, 0), + vir_uniform_ui(c, 0)); + } + break; + + case nir_intrinsic_discard_if: { + /* true (~0) if we're discarding */ + struct qreg cond = ntq_get_src(c, instr->src[0], 0); + + if (c->execute.file != QFILE_NULL) { + /* execute == 0 means the channel is active. Invert + * the condition so that we can use zero as "executing + * and discarding." + */ + vir_PF(c, vir_AND(c, c->execute, vir_NOT(c, cond)), + V3D_QPU_PF_PUSHZ); + vir_set_cond(vir_SETMSF_dest(c, vir_reg(QFILE_NULL, 0), + vir_uniform_ui(c, 0)), + V3D_QPU_COND_IFA); + } else { + vir_PF(c, cond, V3D_QPU_PF_PUSHZ); + vir_set_cond(vir_SETMSF_dest(c, vir_reg(QFILE_NULL, 0), + vir_uniform_ui(c, 0)), + V3D_QPU_COND_IFNA); + } + + break; + } + + default: + fprintf(stderr, "Unknown intrinsic: "); + nir_print_instr(&instr->instr, stderr); + fprintf(stderr, "\n"); + break; + } +} + +/* Clears (activates) the execute flags for any channels whose jump target + * matches this block. + */ +static void +ntq_activate_execute_for_block(struct v3d_compile *c) +{ + vir_PF(c, vir_SUB(c, c->execute, vir_uniform_ui(c, c->cur_block->index)), + V3D_QPU_PF_PUSHZ); + + vir_MOV_cond(c, V3D_QPU_COND_IFA, c->execute, vir_uniform_ui(c, 0)); +} + +static void +ntq_emit_if(struct v3d_compile *c, nir_if *if_stmt) +{ + nir_block *nir_else_block = nir_if_first_else_block(if_stmt); + bool empty_else_block = + (nir_else_block == nir_if_last_else_block(if_stmt) && + exec_list_is_empty(&nir_else_block->instr_list)); + + struct qblock *then_block = vir_new_block(c); + struct qblock *after_block = vir_new_block(c); + struct qblock *else_block; + if (empty_else_block) + else_block = after_block; + else + else_block = vir_new_block(c); + + bool was_top_level = false; + if (c->execute.file == QFILE_NULL) { + c->execute = vir_MOV(c, vir_uniform_ui(c, 0)); + was_top_level = true; + } + + /* Set A for executing (execute == 0) and jumping (if->condition == + * 0) channels, and then update execute flags for those to point to + * the ELSE block. + */ + vir_PF(c, vir_OR(c, + c->execute, + ntq_get_src(c, if_stmt->condition, 0)), + V3D_QPU_PF_PUSHZ); + vir_MOV_cond(c, V3D_QPU_COND_IFA, + c->execute, + vir_uniform_ui(c, else_block->index)); + + /* Jump to ELSE if nothing is active for THEN, otherwise fall + * through. + */ + vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ); + vir_BRANCH(c, V3D_QPU_BRANCH_COND_ALLNA); + vir_link_blocks(c->cur_block, else_block); + vir_link_blocks(c->cur_block, then_block); + + /* Process the THEN block. */ + vir_set_emit_block(c, then_block); + ntq_emit_cf_list(c, &if_stmt->then_list); + + if (!empty_else_block) { + /* Handle the end of the THEN block. First, all currently + * active channels update their execute flags to point to + * ENDIF + */ + vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ); + vir_MOV_cond(c, V3D_QPU_COND_IFA, c->execute, + vir_uniform_ui(c, after_block->index)); + + /* If everything points at ENDIF, then jump there immediately. */ + vir_PF(c, vir_SUB(c, c->execute, + vir_uniform_ui(c, after_block->index)), + V3D_QPU_PF_PUSHZ); + vir_BRANCH(c, V3D_QPU_BRANCH_COND_ALLA); + vir_link_blocks(c->cur_block, after_block); + vir_link_blocks(c->cur_block, else_block); + + vir_set_emit_block(c, else_block); + ntq_activate_execute_for_block(c); + ntq_emit_cf_list(c, &if_stmt->else_list); + } + + vir_link_blocks(c->cur_block, after_block); + + vir_set_emit_block(c, after_block); + if (was_top_level) + c->execute = c->undef; + else + ntq_activate_execute_for_block(c); +} + +static void +ntq_emit_jump(struct v3d_compile *c, nir_jump_instr *jump) +{ + switch (jump->type) { + case nir_jump_break: + vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ); + vir_MOV_cond(c, V3D_QPU_COND_IFA, c->execute, + vir_uniform_ui(c, c->loop_break_block->index)); + break; + + case nir_jump_continue: + vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ); + vir_MOV_cond(c, V3D_QPU_COND_IFA, c->execute, + vir_uniform_ui(c, c->loop_cont_block->index)); + break; + + case nir_jump_return: + unreachable("All returns shouold be lowered\n"); + } +} + +static void +ntq_emit_instr(struct v3d_compile *c, nir_instr *instr) +{ + switch (instr->type) { + case nir_instr_type_alu: + ntq_emit_alu(c, nir_instr_as_alu(instr)); + break; + + case nir_instr_type_intrinsic: + ntq_emit_intrinsic(c, nir_instr_as_intrinsic(instr)); + break; + + case nir_instr_type_load_const: + ntq_emit_load_const(c, nir_instr_as_load_const(instr)); + break; + + case nir_instr_type_ssa_undef: + ntq_emit_ssa_undef(c, nir_instr_as_ssa_undef(instr)); + break; + + case nir_instr_type_tex: + ntq_emit_tex(c, nir_instr_as_tex(instr)); + break; + + case nir_instr_type_jump: + ntq_emit_jump(c, nir_instr_as_jump(instr)); + break; + + default: + fprintf(stderr, "Unknown NIR instr type: "); + nir_print_instr(instr, stderr); + fprintf(stderr, "\n"); + abort(); + } +} + +static void +ntq_emit_block(struct v3d_compile *c, nir_block *block) +{ + nir_foreach_instr(instr, block) { + ntq_emit_instr(c, instr); + } +} + +static void ntq_emit_cf_list(struct v3d_compile *c, struct exec_list *list); + +static void +ntq_emit_loop(struct v3d_compile *c, nir_loop *loop) +{ + bool was_top_level = false; + if (c->execute.file == QFILE_NULL) { + c->execute = vir_MOV(c, vir_uniform_ui(c, 0)); + was_top_level = true; + } + + struct qblock *save_loop_cont_block = c->loop_cont_block; + struct qblock *save_loop_break_block = c->loop_break_block; + + c->loop_cont_block = vir_new_block(c); + c->loop_break_block = vir_new_block(c); + + vir_link_blocks(c->cur_block, c->loop_cont_block); + vir_set_emit_block(c, c->loop_cont_block); + ntq_activate_execute_for_block(c); + + ntq_emit_cf_list(c, &loop->body); + + /* Re-enable any previous continues now, so our ANYA check below + * works. + * + * XXX: Use the .ORZ flags update, instead. + */ + vir_PF(c, vir_SUB(c, + c->execute, + vir_uniform_ui(c, c->loop_cont_block->index)), + V3D_QPU_PF_PUSHZ); + vir_MOV_cond(c, V3D_QPU_COND_IFA, c->execute, vir_uniform_ui(c, 0)); + + vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ); + + vir_BRANCH(c, V3D_QPU_BRANCH_COND_ANYA); + vir_link_blocks(c->cur_block, c->loop_cont_block); + vir_link_blocks(c->cur_block, c->loop_break_block); + + vir_set_emit_block(c, c->loop_break_block); + if (was_top_level) + c->execute = c->undef; + else + ntq_activate_execute_for_block(c); + + c->loop_break_block = save_loop_break_block; + c->loop_cont_block = save_loop_cont_block; +} + +static void +ntq_emit_function(struct v3d_compile *c, nir_function_impl *func) +{ + fprintf(stderr, "FUNCTIONS not handled.\n"); + abort(); +} + +static void +ntq_emit_cf_list(struct v3d_compile *c, struct exec_list *list) +{ + foreach_list_typed(nir_cf_node, node, node, list) { + switch (node->type) { + case nir_cf_node_block: + ntq_emit_block(c, nir_cf_node_as_block(node)); + break; + + case nir_cf_node_if: + ntq_emit_if(c, nir_cf_node_as_if(node)); + break; + + case nir_cf_node_loop: + ntq_emit_loop(c, nir_cf_node_as_loop(node)); + break; + + case nir_cf_node_function: + ntq_emit_function(c, nir_cf_node_as_function(node)); + break; + + default: + fprintf(stderr, "Unknown NIR node type\n"); + abort(); + } + } +} + +static void +ntq_emit_impl(struct v3d_compile *c, nir_function_impl *impl) +{ + ntq_setup_registers(c, &impl->registers); + ntq_emit_cf_list(c, &impl->body); +} + +static void +nir_to_vir(struct v3d_compile *c) +{ + if (c->s->info.stage == MESA_SHADER_FRAGMENT) { + c->payload_w = vir_MOV(c, vir_reg(QFILE_REG, 0)); + c->payload_w_centroid = vir_MOV(c, vir_reg(QFILE_REG, 1)); + c->payload_z = vir_MOV(c, vir_reg(QFILE_REG, 2)); + + if (c->fs_key->is_points) { + c->point_x = emit_fragment_varying(c, NULL, 0); + c->point_y = emit_fragment_varying(c, NULL, 0); + } else if (c->fs_key->is_lines) { + c->line_x = emit_fragment_varying(c, NULL, 0); + } + } + + ntq_setup_inputs(c); + ntq_setup_outputs(c); + ntq_setup_uniforms(c); + ntq_setup_registers(c, &c->s->registers); + + /* Find the main function and emit the body. */ + nir_foreach_function(function, c->s) { + assert(strcmp(function->name, "main") == 0); + assert(function->impl); + ntq_emit_impl(c, function->impl); + } +} + +const nir_shader_compiler_options v3d_nir_options = { + .lower_extract_byte = true, + .lower_extract_word = true, + .lower_bitfield_insert = true, + .lower_bitfield_extract = true, + .lower_pack_unorm_2x16 = true, + .lower_pack_snorm_2x16 = true, + .lower_pack_unorm_4x8 = true, + .lower_pack_snorm_4x8 = true, + .lower_ffma = true, + .lower_flrp32 = true, + .lower_fpow = true, + .lower_fsat = true, + .lower_fsqrt = true, + .lower_negate = true, + .native_integers = true, +}; + + +#if 0 +static int +count_nir_instrs(nir_shader *nir) +{ + int count = 0; + nir_foreach_function(function, nir) { + if (!function->impl) + continue; + nir_foreach_block(block, function->impl) { + nir_foreach_instr(instr, block) + count++; + } + } + return count; +} +#endif + +void +v3d_nir_to_vir(struct v3d_compile *c) +{ + if (V3D_DEBUG & (V3D_DEBUG_NIR | + v3d_debug_flag_for_shader_stage(c->s->info.stage))) { + fprintf(stderr, "%s prog %d/%d NIR:\n", + vir_get_stage_name(c), + c->program_id, c->variant_id); + nir_print_shader(c->s, stderr); + } + + nir_to_vir(c); + + switch (c->s->info.stage) { + case MESA_SHADER_FRAGMENT: + emit_frag_end(c); + break; + case MESA_SHADER_VERTEX: + emit_vert_end(c); + break; + default: + unreachable("bad stage"); + } + + if (V3D_DEBUG & (V3D_DEBUG_VIR | + v3d_debug_flag_for_shader_stage(c->s->info.stage))) { + fprintf(stderr, "%s prog %d/%d pre-opt VIR:\n", + vir_get_stage_name(c), + c->program_id, c->variant_id); + vir_dump(c); + fprintf(stderr, "\n"); + } + + vir_optimize(c); + vir_lower_uniforms(c); + + /* XXX: vir_schedule_instructions(c); */ + + if (V3D_DEBUG & (V3D_DEBUG_VIR | + v3d_debug_flag_for_shader_stage(c->s->info.stage))) { + fprintf(stderr, "%s prog %d/%d VIR:\n", + vir_get_stage_name(c), + c->program_id, c->variant_id); + vir_dump(c); + fprintf(stderr, "\n"); + } + + v3d_vir_to_qpu(c); +} diff --git a/lib/mesa/src/broadcom/compiler/qpu_schedule.c b/lib/mesa/src/broadcom/compiler/qpu_schedule.c new file mode 100644 index 000000000..dd221e027 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/qpu_schedule.c @@ -0,0 +1,1365 @@ +/* + * Copyright © 2010 Intel Corporation + * Copyright © 2014-2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/** + * @file + * + * The basic model of the list scheduler is to take a basic block, compute a + * DAG of the dependencies, and make a list of the DAG heads. Heuristically + * pick a DAG head, then put all the children that are now DAG heads into the + * list of things to schedule. + * + * The goal of scheduling here is to pack pairs of operations together in a + * single QPU instruction. + */ + +#include "qpu/qpu_disasm.h" +#include "v3d_compiler.h" +#include "util/ralloc.h" + +static bool debug; + +struct schedule_node_child; + +struct schedule_node { + struct list_head link; + struct qinst *inst; + struct schedule_node_child *children; + uint32_t child_count; + uint32_t child_array_size; + uint32_t parent_count; + + /* Longest cycles + instruction_latency() of any parent of this node. */ + uint32_t unblocked_time; + + /** + * Minimum number of cycles from scheduling this instruction until the + * end of the program, based on the slowest dependency chain through + * the children. + */ + uint32_t delay; + + /** + * cycles between this instruction being scheduled and when its result + * can be consumed. + */ + uint32_t latency; +}; + +struct schedule_node_child { + struct schedule_node *node; + bool write_after_read; +}; + +/* When walking the instructions in reverse, we need to swap before/after in + * add_dep(). + */ +enum direction { F, R }; + +struct schedule_state { + struct schedule_node *last_r[6]; + struct schedule_node *last_rf[64]; + struct schedule_node *last_sf; + struct schedule_node *last_vpm_read; + struct schedule_node *last_tmu_write; + struct schedule_node *last_tlb; + struct schedule_node *last_vpm; + struct schedule_node *last_unif; + struct schedule_node *last_rtop; + enum direction dir; + /* Estimated cycle when the current instruction would start. */ + uint32_t time; +}; + +static void +add_dep(struct schedule_state *state, + struct schedule_node *before, + struct schedule_node *after, + bool write) +{ + bool write_after_read = !write && state->dir == R; + + if (!before || !after) + return; + + assert(before != after); + + if (state->dir == R) { + struct schedule_node *t = before; + before = after; + after = t; + } + + for (int i = 0; i < before->child_count; i++) { + if (before->children[i].node == after && + (before->children[i].write_after_read == write_after_read)) { + return; + } + } + + if (before->child_array_size <= before->child_count) { + before->child_array_size = MAX2(before->child_array_size * 2, 16); + before->children = reralloc(before, before->children, + struct schedule_node_child, + before->child_array_size); + } + + before->children[before->child_count].node = after; + before->children[before->child_count].write_after_read = + write_after_read; + before->child_count++; + after->parent_count++; +} + +static void +add_read_dep(struct schedule_state *state, + struct schedule_node *before, + struct schedule_node *after) +{ + add_dep(state, before, after, false); +} + +static void +add_write_dep(struct schedule_state *state, + struct schedule_node **before, + struct schedule_node *after) +{ + add_dep(state, *before, after, true); + *before = after; +} + +static bool +qpu_inst_is_tlb(const struct v3d_qpu_instr *inst) +{ + if (inst->type != V3D_QPU_INSTR_TYPE_ALU) + return false; + + if (inst->alu.add.magic_write && + (inst->alu.add.waddr == V3D_QPU_WADDR_TLB || + inst->alu.add.waddr == V3D_QPU_WADDR_TLBU)) + return true; + + if (inst->alu.mul.magic_write && + (inst->alu.mul.waddr == V3D_QPU_WADDR_TLB || + inst->alu.mul.waddr == V3D_QPU_WADDR_TLBU)) + return true; + + return false; +} + +static void +process_mux_deps(struct schedule_state *state, struct schedule_node *n, + enum v3d_qpu_mux mux) +{ + switch (mux) { + case V3D_QPU_MUX_A: + add_read_dep(state, state->last_rf[n->inst->qpu.raddr_a], n); + break; + case V3D_QPU_MUX_B: + add_read_dep(state, state->last_rf[n->inst->qpu.raddr_b], n); + break; + default: + add_read_dep(state, state->last_r[mux - V3D_QPU_MUX_R0], n); + break; + } +} + + +static void +process_waddr_deps(struct schedule_state *state, struct schedule_node *n, + uint32_t waddr, bool magic) +{ + if (!magic) { + add_write_dep(state, &state->last_rf[waddr], n); + } else if (v3d_qpu_magic_waddr_is_tmu(waddr)) { + add_write_dep(state, &state->last_tmu_write, n); + } else if (v3d_qpu_magic_waddr_is_sfu(waddr)) { + /* Handled by v3d_qpu_writes_r4() check. */ + } else { + switch (waddr) { + case V3D_QPU_WADDR_R0: + case V3D_QPU_WADDR_R1: + case V3D_QPU_WADDR_R2: + case V3D_QPU_WADDR_R3: + case V3D_QPU_WADDR_R4: + case V3D_QPU_WADDR_R5: + add_write_dep(state, + &state->last_r[waddr - V3D_QPU_WADDR_R0], + n); + break; + + case V3D_QPU_WADDR_VPM: + case V3D_QPU_WADDR_VPMU: + add_write_dep(state, &state->last_vpm, n); + break; + + case V3D_QPU_WADDR_TLB: + case V3D_QPU_WADDR_TLBU: + add_write_dep(state, &state->last_tlb, n); + break; + + case V3D_QPU_WADDR_NOP: + break; + + default: + fprintf(stderr, "Unknown waddr %d\n", waddr); + abort(); + } + } +} + +static void +process_cond_deps(struct schedule_state *state, struct schedule_node *n, + enum v3d_qpu_cond cond) +{ + if (cond != V3D_QPU_COND_NONE) + add_read_dep(state, state->last_sf, n); +} + +static void +process_pf_deps(struct schedule_state *state, struct schedule_node *n, + enum v3d_qpu_pf pf) +{ + if (pf != V3D_QPU_PF_NONE) + add_write_dep(state, &state->last_sf, n); +} + +static void +process_uf_deps(struct schedule_state *state, struct schedule_node *n, + enum v3d_qpu_uf uf) +{ + if (uf != V3D_QPU_UF_NONE) + add_write_dep(state, &state->last_sf, n); +} + +/** + * Common code for dependencies that need to be tracked both forward and + * backward. + * + * This is for things like "all reads of r4 have to happen between the r4 + * writes that surround them". + */ +static void +calculate_deps(struct schedule_state *state, struct schedule_node *n) +{ + struct qinst *qinst = n->inst; + struct v3d_qpu_instr *inst = &qinst->qpu; + + if (inst->type == V3D_QPU_INSTR_TYPE_BRANCH) { + if (inst->branch.cond != V3D_QPU_BRANCH_COND_ALWAYS) + add_read_dep(state, state->last_sf, n); + + /* XXX: BDI */ + /* XXX: BDU */ + /* XXX: ub */ + /* XXX: raddr_a */ + + add_write_dep(state, &state->last_unif, n); + return; + } + + assert(inst->type == V3D_QPU_INSTR_TYPE_ALU); + + /* XXX: LOAD_IMM */ + + if (v3d_qpu_add_op_num_src(inst->alu.add.op) > 0) + process_mux_deps(state, n, inst->alu.add.a); + if (v3d_qpu_add_op_num_src(inst->alu.add.op) > 1) + process_mux_deps(state, n, inst->alu.add.b); + + if (v3d_qpu_mul_op_num_src(inst->alu.mul.op) > 0) + process_mux_deps(state, n, inst->alu.mul.a); + if (v3d_qpu_mul_op_num_src(inst->alu.mul.op) > 1) + process_mux_deps(state, n, inst->alu.mul.b); + + switch (inst->alu.add.op) { + case V3D_QPU_A_VPMSETUP: + /* Could distinguish read/write by unpacking the uniform. */ + add_write_dep(state, &state->last_vpm, n); + add_write_dep(state, &state->last_vpm_read, n); + break; + + case V3D_QPU_A_STVPMV: + case V3D_QPU_A_STVPMD: + case V3D_QPU_A_STVPMP: + add_write_dep(state, &state->last_vpm, n); + break; + + case V3D_QPU_A_MSF: + add_read_dep(state, state->last_tlb, n); + break; + + case V3D_QPU_A_SETMSF: + case V3D_QPU_A_SETREVF: + add_write_dep(state, &state->last_tlb, n); + break; + + case V3D_QPU_A_FLAPUSH: + case V3D_QPU_A_FLBPUSH: + case V3D_QPU_A_VFLA: + case V3D_QPU_A_VFLNA: + case V3D_QPU_A_VFLB: + case V3D_QPU_A_VFLNB: + add_read_dep(state, state->last_sf, n); + break; + + case V3D_QPU_A_FLBPOP: + add_write_dep(state, &state->last_sf, n); + break; + + default: + break; + } + + switch (inst->alu.mul.op) { + case V3D_QPU_M_MULTOP: + case V3D_QPU_M_UMUL24: + /* MULTOP sets rtop, and UMUL24 implicitly reads rtop and + * resets it to 0. We could possibly reorder umul24s relative + * to each other, but for now just keep all the MUL parts in + * order. + */ + add_write_dep(state, &state->last_rtop, n); + break; + default: + break; + } + + if (inst->alu.add.op != V3D_QPU_A_NOP) { + process_waddr_deps(state, n, inst->alu.add.waddr, + inst->alu.add.magic_write); + } + if (inst->alu.mul.op != V3D_QPU_M_NOP) { + process_waddr_deps(state, n, inst->alu.mul.waddr, + inst->alu.mul.magic_write); + } + + if (v3d_qpu_writes_r3(inst)) + add_write_dep(state, &state->last_r[3], n); + if (v3d_qpu_writes_r4(inst)) + add_write_dep(state, &state->last_r[4], n); + if (v3d_qpu_writes_r5(inst)) + add_write_dep(state, &state->last_r[5], n); + + if (inst->sig.thrsw) { + /* All accumulator contents and flags are undefined after the + * switch. + */ + for (int i = 0; i < ARRAY_SIZE(state->last_r); i++) + add_write_dep(state, &state->last_r[i], n); + add_write_dep(state, &state->last_sf, n); + + /* Scoreboard-locking operations have to stay after the last + * thread switch. + */ + add_write_dep(state, &state->last_tlb, n); + + add_write_dep(state, &state->last_tmu_write, n); + } + + if (inst->sig.ldtmu) { + /* TMU loads are coming from a FIFO, so ordering is important. + */ + add_write_dep(state, &state->last_tmu_write, n); + } + + if (inst->sig.ldtlb | inst->sig.ldtlbu) + add_read_dep(state, state->last_tlb, n); + + if (inst->sig.ldvpm) + add_write_dep(state, &state->last_vpm_read, n); + + /* inst->sig.ldunif or sideband uniform read */ + if (qinst->uniform != ~0) + add_write_dep(state, &state->last_unif, n); + + process_cond_deps(state, n, inst->flags.ac); + process_cond_deps(state, n, inst->flags.mc); + process_pf_deps(state, n, inst->flags.apf); + process_pf_deps(state, n, inst->flags.mpf); + process_uf_deps(state, n, inst->flags.auf); + process_uf_deps(state, n, inst->flags.muf); +} + +static void +calculate_forward_deps(struct v3d_compile *c, struct list_head *schedule_list) +{ + struct schedule_state state; + + memset(&state, 0, sizeof(state)); + state.dir = F; + + list_for_each_entry(struct schedule_node, node, schedule_list, link) + calculate_deps(&state, node); +} + +static void +calculate_reverse_deps(struct v3d_compile *c, struct list_head *schedule_list) +{ + struct list_head *node; + struct schedule_state state; + + memset(&state, 0, sizeof(state)); + state.dir = R; + + for (node = schedule_list->prev; schedule_list != node; node = node->prev) { + calculate_deps(&state, (struct schedule_node *)node); + } +} + +struct choose_scoreboard { + int tick; + int last_sfu_write_tick; + int last_ldvary_tick; + int last_uniforms_reset_tick; + uint32_t last_waddr_add, last_waddr_mul; + bool tlb_locked; +}; + +static bool +mux_reads_too_soon(struct choose_scoreboard *scoreboard, + const struct v3d_qpu_instr *inst, enum v3d_qpu_mux mux) +{ + switch (mux) { + case V3D_QPU_MUX_A: + if (scoreboard->last_waddr_add == inst->raddr_a || + scoreboard->last_waddr_mul == inst->raddr_a) { + return true; + } + break; + + case V3D_QPU_MUX_B: + if (scoreboard->last_waddr_add == inst->raddr_b || + scoreboard->last_waddr_mul == inst->raddr_b) { + return true; + } + break; + + case V3D_QPU_MUX_R4: + if (scoreboard->tick - scoreboard->last_sfu_write_tick <= 2) + return true; + break; + + case V3D_QPU_MUX_R5: + if (scoreboard->tick - scoreboard->last_ldvary_tick <= 1) + return true; + break; + default: + break; + } + + return false; +} + +static bool +reads_too_soon_after_write(struct choose_scoreboard *scoreboard, + struct qinst *qinst) +{ + const struct v3d_qpu_instr *inst = &qinst->qpu; + + /* XXX: Branching off of raddr. */ + if (inst->type == V3D_QPU_INSTR_TYPE_BRANCH) + return false; + + assert(inst->type == V3D_QPU_INSTR_TYPE_ALU); + + if (inst->alu.add.op != V3D_QPU_A_NOP) { + if (v3d_qpu_add_op_num_src(inst->alu.add.op) > 0 && + mux_reads_too_soon(scoreboard, inst, inst->alu.add.a)) { + return true; + } + if (v3d_qpu_add_op_num_src(inst->alu.add.op) > 1 && + mux_reads_too_soon(scoreboard, inst, inst->alu.add.b)) { + return true; + } + } + + if (inst->alu.mul.op != V3D_QPU_M_NOP) { + if (v3d_qpu_mul_op_num_src(inst->alu.mul.op) > 0 && + mux_reads_too_soon(scoreboard, inst, inst->alu.mul.a)) { + return true; + } + if (v3d_qpu_mul_op_num_src(inst->alu.mul.op) > 1 && + mux_reads_too_soon(scoreboard, inst, inst->alu.mul.b)) { + return true; + } + } + + /* XXX: imm */ + + return false; +} + +static bool +writes_too_soon_after_write(struct choose_scoreboard *scoreboard, + struct qinst *qinst) +{ + const struct v3d_qpu_instr *inst = &qinst->qpu; + + /* Don't schedule any other r4 write too soon after an SFU write. + * This would normally be prevented by dependency tracking, but might + * occur if a dead SFU computation makes it to scheduling. + */ + if (scoreboard->tick - scoreboard->last_sfu_write_tick < 2 && + v3d_qpu_writes_r4(inst)) + return true; + + return false; +} + +static bool +pixel_scoreboard_too_soon(struct choose_scoreboard *scoreboard, + const struct v3d_qpu_instr *inst) +{ + return (scoreboard->tick == 0 && qpu_inst_is_tlb(inst)); +} + +static int +get_instruction_priority(const struct v3d_qpu_instr *inst) +{ + uint32_t baseline_score; + uint32_t next_score = 0; + + /* Schedule TLB operations as late as possible, to get more + * parallelism between shaders. + */ + if (qpu_inst_is_tlb(inst)) + return next_score; + next_score++; + + /* Schedule texture read results collection late to hide latency. */ + if (inst->sig.ldtmu) + return next_score; + next_score++; + + /* Default score for things that aren't otherwise special. */ + baseline_score = next_score; + next_score++; + + /* Schedule texture read setup early to hide their latency better. */ + if (inst->type == V3D_QPU_INSTR_TYPE_ALU && + ((inst->alu.add.magic_write && + v3d_qpu_magic_waddr_is_tmu(inst->alu.add.waddr)) || + (inst->alu.mul.magic_write && + v3d_qpu_magic_waddr_is_tmu(inst->alu.mul.waddr)))) { + return next_score; + } + next_score++; + + return baseline_score; +} + +static bool +qpu_magic_waddr_is_periph(enum v3d_qpu_waddr waddr) +{ + return (v3d_qpu_magic_waddr_is_tmu(waddr) || + v3d_qpu_magic_waddr_is_sfu(waddr) || + v3d_qpu_magic_waddr_is_tlb(waddr) || + v3d_qpu_magic_waddr_is_vpm(waddr) || + v3d_qpu_magic_waddr_is_tsy(waddr)); +} + +static bool +qpu_accesses_peripheral(const struct v3d_qpu_instr *inst) +{ + if (inst->type == V3D_QPU_INSTR_TYPE_ALU) { + if (inst->alu.add.op != V3D_QPU_A_NOP && + inst->alu.add.magic_write && + qpu_magic_waddr_is_periph(inst->alu.add.waddr)) { + return true; + } + + if (inst->alu.add.op == V3D_QPU_A_VPMSETUP) + return true; + + if (inst->alu.mul.op != V3D_QPU_M_NOP && + inst->alu.mul.magic_write && + qpu_magic_waddr_is_periph(inst->alu.mul.waddr)) { + return true; + } + } + + return (inst->sig.ldvpm || + inst->sig.ldtmu || + inst->sig.ldtlb || + inst->sig.ldtlbu); +} + +static bool +qpu_merge_inst(const struct v3d_device_info *devinfo, + struct v3d_qpu_instr *result, + const struct v3d_qpu_instr *a, + const struct v3d_qpu_instr *b) +{ + if (a->type != V3D_QPU_INSTR_TYPE_ALU || + b->type != V3D_QPU_INSTR_TYPE_ALU) { + return false; + } + + /* Can't do more than one peripheral access in an instruction. */ + if (qpu_accesses_peripheral(a) && qpu_accesses_peripheral(b)) + return false; + + struct v3d_qpu_instr merge = *a; + + if (b->alu.add.op != V3D_QPU_A_NOP) { + if (a->alu.add.op != V3D_QPU_A_NOP) + return false; + merge.alu.add = b->alu.add; + + merge.flags.ac = b->flags.ac; + merge.flags.apf = b->flags.apf; + merge.flags.auf = b->flags.auf; + } + + if (b->alu.mul.op != V3D_QPU_M_NOP) { + if (a->alu.mul.op != V3D_QPU_M_NOP) + return false; + merge.alu.mul = b->alu.mul; + + merge.flags.mc = b->flags.mc; + merge.flags.mpf = b->flags.mpf; + merge.flags.muf = b->flags.muf; + } + + if (v3d_qpu_uses_mux(b, V3D_QPU_MUX_A)) { + if (v3d_qpu_uses_mux(a, V3D_QPU_MUX_A) && + a->raddr_a != b->raddr_a) { + return false; + } + merge.raddr_a = b->raddr_a; + } + + if (v3d_qpu_uses_mux(b, V3D_QPU_MUX_B)) { + if (v3d_qpu_uses_mux(a, V3D_QPU_MUX_B) && + a->raddr_b != b->raddr_b) { + return false; + } + merge.raddr_b = b->raddr_b; + } + + merge.sig.thrsw |= b->sig.thrsw; + merge.sig.ldunif |= b->sig.ldunif; + merge.sig.ldtmu |= b->sig.ldtmu; + merge.sig.ldvary |= b->sig.ldvary; + merge.sig.ldvpm |= b->sig.ldvpm; + merge.sig.small_imm |= b->sig.small_imm; + merge.sig.ldtlb |= b->sig.ldtlb; + merge.sig.ldtlbu |= b->sig.ldtlbu; + merge.sig.ucb |= b->sig.ucb; + merge.sig.rotate |= b->sig.rotate; + merge.sig.wrtmuc |= b->sig.wrtmuc; + + uint64_t packed; + bool ok = v3d_qpu_instr_pack(devinfo, &merge, &packed); + + *result = merge; + /* No modifying the real instructions on failure. */ + assert(ok || (a != result && b != result)); + + return ok; +} + +static struct schedule_node * +choose_instruction_to_schedule(const struct v3d_device_info *devinfo, + struct choose_scoreboard *scoreboard, + struct list_head *schedule_list, + struct schedule_node *prev_inst) +{ + struct schedule_node *chosen = NULL; + int chosen_prio = 0; + + /* Don't pair up anything with a thread switch signal -- emit_thrsw() + * will handle pairing it along with filling the delay slots. + */ + if (prev_inst) { + if (prev_inst->inst->qpu.sig.thrsw) + return NULL; + } + + list_for_each_entry(struct schedule_node, n, schedule_list, link) { + const struct v3d_qpu_instr *inst = &n->inst->qpu; + + /* Don't choose the branch instruction until it's the last one + * left. We'll move it up to fit its delay slots after we + * choose it. + */ + if (inst->type == V3D_QPU_INSTR_TYPE_BRANCH && + !list_is_singular(schedule_list)) { + continue; + } + + /* "An instruction must not read from a location in physical + * regfile A or B that was written to by the previous + * instruction." + */ + if (reads_too_soon_after_write(scoreboard, n->inst)) + continue; + + if (writes_too_soon_after_write(scoreboard, n->inst)) + continue; + + /* "A scoreboard wait must not occur in the first two + * instructions of a fragment shader. This is either the + * explicit Wait for Scoreboard signal or an implicit wait + * with the first tile-buffer read or write instruction." + */ + if (pixel_scoreboard_too_soon(scoreboard, inst)) + continue; + + /* ldunif and ldvary both write r5, but ldunif does so a tick + * sooner. If the ldvary's r5 wasn't used, then ldunif might + * otherwise get scheduled so ldunif and ldvary try to update + * r5 in the same tick. + */ + if (inst->sig.ldunif && + scoreboard->tick == scoreboard->last_ldvary_tick + 1) { + continue; + } + + /* If we're trying to pair with another instruction, check + * that they're compatible. + */ + if (prev_inst) { + /* Don't pair up a thread switch signal -- we'll + * handle pairing it when we pick it on its own. + */ + if (inst->sig.thrsw) + continue; + + if (prev_inst->inst->uniform != -1 && + n->inst->uniform != -1) + continue; + + /* Don't merge in something that will lock the TLB. + * Hopwefully what we have in inst will release some + * other instructions, allowing us to delay the + * TLB-locking instruction until later. + */ + if (!scoreboard->tlb_locked && qpu_inst_is_tlb(inst)) + continue; + + struct v3d_qpu_instr merged_inst; + if (!qpu_merge_inst(devinfo, &merged_inst, + &prev_inst->inst->qpu, inst)) { + continue; + } + } + + int prio = get_instruction_priority(inst); + + /* Found a valid instruction. If nothing better comes along, + * this one works. + */ + if (!chosen) { + chosen = n; + chosen_prio = prio; + continue; + } + + if (prio > chosen_prio) { + chosen = n; + chosen_prio = prio; + } else if (prio < chosen_prio) { + continue; + } + + if (n->delay > chosen->delay) { + chosen = n; + chosen_prio = prio; + } else if (n->delay < chosen->delay) { + continue; + } + } + + return chosen; +} + +static void +update_scoreboard_for_magic_waddr(struct choose_scoreboard *scoreboard, + enum v3d_qpu_waddr waddr) +{ + if (v3d_qpu_magic_waddr_is_sfu(waddr)) + scoreboard->last_sfu_write_tick = scoreboard->tick; +} + +static void +update_scoreboard_for_chosen(struct choose_scoreboard *scoreboard, + const struct v3d_qpu_instr *inst) +{ + scoreboard->last_waddr_add = ~0; + scoreboard->last_waddr_mul = ~0; + + if (inst->type == V3D_QPU_INSTR_TYPE_BRANCH) + return; + + assert(inst->type == V3D_QPU_INSTR_TYPE_ALU); + + if (inst->alu.add.op != V3D_QPU_A_NOP) { + if (inst->alu.add.magic_write) { + update_scoreboard_for_magic_waddr(scoreboard, + inst->alu.add.waddr); + } else { + scoreboard->last_waddr_add = inst->alu.add.waddr; + } + } + + if (inst->alu.mul.op != V3D_QPU_M_NOP) { + if (inst->alu.mul.magic_write) { + update_scoreboard_for_magic_waddr(scoreboard, + inst->alu.mul.waddr); + } else { + scoreboard->last_waddr_mul = inst->alu.mul.waddr; + } + } + + if (inst->sig.ldvary) + scoreboard->last_ldvary_tick = scoreboard->tick; + + if (qpu_inst_is_tlb(inst)) + scoreboard->tlb_locked = true; +} + +static void +dump_state(const struct v3d_device_info *devinfo, + struct list_head *schedule_list) +{ + list_for_each_entry(struct schedule_node, n, schedule_list, link) { + fprintf(stderr, " t=%4d: ", n->unblocked_time); + v3d_qpu_dump(devinfo, &n->inst->qpu); + fprintf(stderr, "\n"); + + for (int i = 0; i < n->child_count; i++) { + struct schedule_node *child = n->children[i].node; + if (!child) + continue; + + fprintf(stderr, " - "); + v3d_qpu_dump(devinfo, &child->inst->qpu); + fprintf(stderr, " (%d parents, %c)\n", + child->parent_count, + n->children[i].write_after_read ? 'w' : 'r'); + } + } +} + +static uint32_t magic_waddr_latency(enum v3d_qpu_waddr waddr, + const struct v3d_qpu_instr *after) +{ + /* Apply some huge latency between texture fetch requests and getting + * their results back. + * + * FIXME: This is actually pretty bogus. If we do: + * + * mov tmu0_s, a + * <a bit of math> + * mov tmu0_s, b + * load_tmu0 + * <more math> + * load_tmu0 + * + * we count that as worse than + * + * mov tmu0_s, a + * mov tmu0_s, b + * <lots of math> + * load_tmu0 + * <more math> + * load_tmu0 + * + * because we associate the first load_tmu0 with the *second* tmu0_s. + */ + if (v3d_qpu_magic_waddr_is_tmu(waddr) && after->sig.ldtmu) + return 100; + + /* Assume that anything depending on us is consuming the SFU result. */ + if (v3d_qpu_magic_waddr_is_sfu(waddr)) + return 3; + + return 1; +} + +static uint32_t +instruction_latency(struct schedule_node *before, struct schedule_node *after) +{ + const struct v3d_qpu_instr *before_inst = &before->inst->qpu; + const struct v3d_qpu_instr *after_inst = &after->inst->qpu; + uint32_t latency = 1; + + if (before_inst->type != V3D_QPU_INSTR_TYPE_ALU || + after_inst->type != V3D_QPU_INSTR_TYPE_ALU) + return latency; + + if (before_inst->alu.add.magic_write) { + latency = MAX2(latency, + magic_waddr_latency(before_inst->alu.add.waddr, + after_inst)); + } + + if (before_inst->alu.mul.magic_write) { + latency = MAX2(latency, + magic_waddr_latency(before_inst->alu.mul.waddr, + after_inst)); + } + + return latency; +} + +/** Recursive computation of the delay member of a node. */ +static void +compute_delay(struct schedule_node *n) +{ + if (!n->child_count) { + n->delay = 1; + } else { + for (int i = 0; i < n->child_count; i++) { + if (!n->children[i].node->delay) + compute_delay(n->children[i].node); + n->delay = MAX2(n->delay, + n->children[i].node->delay + + instruction_latency(n, n->children[i].node)); + } + } +} + +static void +mark_instruction_scheduled(struct list_head *schedule_list, + uint32_t time, + struct schedule_node *node, + bool war_only) +{ + if (!node) + return; + + for (int i = node->child_count - 1; i >= 0; i--) { + struct schedule_node *child = + node->children[i].node; + + if (!child) + continue; + + if (war_only && !node->children[i].write_after_read) + continue; + + /* If the requirement is only that the node not appear before + * the last read of its destination, then it can be scheduled + * immediately after (or paired with!) the thing reading the + * destination. + */ + uint32_t latency = 0; + if (!war_only) { + latency = instruction_latency(node, + node->children[i].node); + } + + child->unblocked_time = MAX2(child->unblocked_time, + time + latency); + child->parent_count--; + if (child->parent_count == 0) + list_add(&child->link, schedule_list); + + node->children[i].node = NULL; + } +} + +static struct qinst * +vir_nop() +{ + struct qreg undef = { QFILE_NULL, 0 }; + struct qinst *qinst = vir_add_inst(V3D_QPU_A_NOP, undef, undef, undef); + + return qinst; +} + +#if 0 +static struct qinst * +nop_after(struct qinst *inst) +{ + struct qinst *q = vir_nop(); + + list_add(&q->link, &inst->link); + + return q; +} + +/** + * Emits a THRSW/LTHRSW signal in the stream, trying to move it up to pair + * with another instruction. + */ +static void +emit_thrsw(struct v3d_compile *c, + struct choose_scoreboard *scoreboard, + const struct v3d_qpu_instr *inst) +{ + /* There should be nothing in a thrsw inst being scheduled other than + * the signal bits. + */ + assert(inst->type == V3D_QPU_INSTR_TYPE_ALU); + assert(inst->alu.add.op == V3D_QPU_A_NOP); + assert(inst->alu.mul.op == V3D_QPU_M_NOP); + + /* Try to find an earlier scheduled instruction that we can merge the + * thrsw into. + */ + int thrsw_ip = c->qpu_inst_count; + for (int i = 1; i <= MIN2(c->qpu_inst_count, 3); i++) { + uint64_t prev_instr = c->qpu_insts[c->qpu_inst_count - i]; + uint32_t prev_sig = QPU_GET_FIELD(prev_instr, QPU_SIG); + + if (prev_sig == QPU_SIG_NONE) + thrsw_ip = c->qpu_inst_count - i; + } + + if (thrsw_ip != c->qpu_inst_count) { + /* Merge the thrsw into the existing instruction. */ + c->qpu_insts[thrsw_ip] = + QPU_UPDATE_FIELD(c->qpu_insts[thrsw_ip], sig, QPU_SIG); + } else { + qpu_serialize_one_inst(c, inst); + update_scoreboard_for_chosen(scoreboard, inst); + } + + /* Fill the delay slots. */ + while (c->qpu_inst_count < thrsw_ip + 3) { + update_scoreboard_for_chosen(scoreboard, v3d_qpu_nop()); + qpu_serialize_one_inst(c, v3d_qpu_nop()); + } +} +#endif + +static uint32_t +schedule_instructions(struct v3d_compile *c, + struct choose_scoreboard *scoreboard, + struct qblock *block, + struct list_head *schedule_list, + enum quniform_contents *orig_uniform_contents, + uint32_t *orig_uniform_data, + uint32_t *next_uniform) +{ + const struct v3d_device_info *devinfo = c->devinfo; + uint32_t time = 0; + + if (debug) { + fprintf(stderr, "initial deps:\n"); + dump_state(devinfo, schedule_list); + fprintf(stderr, "\n"); + } + + /* Remove non-DAG heads from the list. */ + list_for_each_entry_safe(struct schedule_node, n, schedule_list, link) { + if (n->parent_count != 0) + list_del(&n->link); + } + + while (!list_empty(schedule_list)) { + struct schedule_node *chosen = + choose_instruction_to_schedule(devinfo, + scoreboard, + schedule_list, + NULL); + struct schedule_node *merge = NULL; + + /* If there are no valid instructions to schedule, drop a NOP + * in. + */ + struct qinst *qinst = chosen ? chosen->inst : vir_nop(); + struct v3d_qpu_instr *inst = &qinst->qpu; + + if (debug) { + fprintf(stderr, "t=%4d: current list:\n", + time); + dump_state(devinfo, schedule_list); + fprintf(stderr, "t=%4d: chose: ", time); + v3d_qpu_dump(devinfo, inst); + fprintf(stderr, "\n"); + } + + /* Schedule this instruction onto the QPU list. Also try to + * find an instruction to pair with it. + */ + if (chosen) { + time = MAX2(chosen->unblocked_time, time); + list_del(&chosen->link); + mark_instruction_scheduled(schedule_list, time, + chosen, true); + + merge = choose_instruction_to_schedule(devinfo, + scoreboard, + schedule_list, + chosen); + if (merge) { + time = MAX2(merge->unblocked_time, time); + list_del(&merge->link); + (void)qpu_merge_inst(devinfo, inst, + inst, &merge->inst->qpu); + if (merge->inst->uniform != -1) { + chosen->inst->uniform = + merge->inst->uniform; + } + + if (debug) { + fprintf(stderr, "t=%4d: merging: ", + time); + v3d_qpu_dump(devinfo, &merge->inst->qpu); + fprintf(stderr, "\n"); + fprintf(stderr, " result: "); + v3d_qpu_dump(devinfo, inst); + fprintf(stderr, "\n"); + } + } + } + + /* Update the uniform index for the rewritten location -- + * branch target updating will still need to change + * c->uniform_data[] using this index. + */ + if (qinst->uniform != -1) { + if (inst->type == V3D_QPU_INSTR_TYPE_BRANCH) + block->branch_uniform = *next_uniform; + + c->uniform_data[*next_uniform] = + orig_uniform_data[qinst->uniform]; + c->uniform_contents[*next_uniform] = + orig_uniform_contents[qinst->uniform]; + qinst->uniform = *next_uniform; + (*next_uniform)++; + } + + if (debug) { + fprintf(stderr, "\n"); + } + + /* Now that we've scheduled a new instruction, some of its + * children can be promoted to the list of instructions ready to + * be scheduled. Update the children's unblocked time for this + * DAG edge as we do so. + */ + mark_instruction_scheduled(schedule_list, time, chosen, false); + + if (merge) { + mark_instruction_scheduled(schedule_list, time, merge, + false); + + /* The merged VIR instruction doesn't get re-added to the + * block, so free it now. + */ + free(merge->inst); + } + + if (0 && inst->sig.thrsw) { + /* XXX emit_thrsw(c, scoreboard, qinst); */ + } else { + c->qpu_inst_count++; + list_addtail(&qinst->link, &block->instructions); + update_scoreboard_for_chosen(scoreboard, inst); + } + + scoreboard->tick++; + time++; + + if (inst->type == V3D_QPU_INSTR_TYPE_BRANCH || + inst->sig.thrsw /* XXX */) { + block->branch_qpu_ip = c->qpu_inst_count - 1; + /* Fill the delay slots. + * + * We should fill these with actual instructions, + * instead, but that will probably need to be done + * after this, once we know what the leading + * instructions of the successors are (so we can + * handle A/B register file write latency) + */ + /* XXX: scoreboard */ + int slots = (inst->type == V3D_QPU_INSTR_TYPE_BRANCH ? + 3 : 2); + for (int i = 0; i < slots; i++) { + struct qinst *nop = vir_nop(); + list_addtail(&nop->link, &block->instructions); + + update_scoreboard_for_chosen(scoreboard, + &nop->qpu); + c->qpu_inst_count++; + scoreboard->tick++; + time++; + } + } + } + + return time; +} + +static uint32_t +qpu_schedule_instructions_block(struct v3d_compile *c, + struct choose_scoreboard *scoreboard, + struct qblock *block, + enum quniform_contents *orig_uniform_contents, + uint32_t *orig_uniform_data, + uint32_t *next_uniform) +{ + void *mem_ctx = ralloc_context(NULL); + struct list_head schedule_list; + + list_inithead(&schedule_list); + + /* Wrap each instruction in a scheduler structure. */ + while (!list_empty(&block->instructions)) { + struct qinst *qinst = (struct qinst *)block->instructions.next; + struct schedule_node *n = + rzalloc(mem_ctx, struct schedule_node); + + n->inst = qinst; + + list_del(&qinst->link); + list_addtail(&n->link, &schedule_list); + } + + calculate_forward_deps(c, &schedule_list); + calculate_reverse_deps(c, &schedule_list); + + list_for_each_entry(struct schedule_node, n, &schedule_list, link) { + compute_delay(n); + } + + uint32_t cycles = schedule_instructions(c, scoreboard, block, + &schedule_list, + orig_uniform_contents, + orig_uniform_data, + next_uniform); + + ralloc_free(mem_ctx); + + return cycles; +} + +static void +qpu_set_branch_targets(struct v3d_compile *c) +{ + vir_for_each_block(block, c) { + /* The end block of the program has no branch. */ + if (!block->successors[0]) + continue; + + /* If there was no branch instruction, then the successor + * block must follow immediately after this one. + */ + if (block->branch_qpu_ip == ~0) { + assert(block->end_qpu_ip + 1 == + block->successors[0]->start_qpu_ip); + continue; + } + + /* Walk back through the delay slots to find the branch + * instr. + */ + struct list_head *entry = block->instructions.prev; + for (int i = 0; i < 3; i++) + entry = entry->prev; + struct qinst *branch = container_of(entry, branch, link); + assert(branch->qpu.type == V3D_QPU_INSTR_TYPE_BRANCH); + + /* Make sure that the if-we-don't-jump + * successor was scheduled just after the + * delay slots. + */ + assert(!block->successors[1] || + block->successors[1]->start_qpu_ip == + block->branch_qpu_ip + 4); + + branch->qpu.branch.offset = + ((block->successors[0]->start_qpu_ip - + (block->branch_qpu_ip + 4)) * + sizeof(uint64_t)); + + /* Set up the relative offset to jump in the + * uniform stream. + * + * Use a temporary here, because + * uniform_data[inst->uniform] may be shared + * between multiple instructions. + */ + assert(c->uniform_contents[branch->uniform] == QUNIFORM_CONSTANT); + c->uniform_data[branch->uniform] = + (block->successors[0]->start_uniform - + (block->branch_uniform + 1)) * 4; + } +} + +uint32_t +v3d_qpu_schedule_instructions(struct v3d_compile *c) +{ + const struct v3d_device_info *devinfo = c->devinfo; + + /* We reorder the uniforms as we schedule instructions, so save the + * old data off and replace it. + */ + uint32_t *uniform_data = c->uniform_data; + enum quniform_contents *uniform_contents = c->uniform_contents; + c->uniform_contents = ralloc_array(c, enum quniform_contents, + c->num_uniforms); + c->uniform_data = ralloc_array(c, uint32_t, c->num_uniforms); + c->uniform_array_size = c->num_uniforms; + uint32_t next_uniform = 0; + + struct choose_scoreboard scoreboard; + memset(&scoreboard, 0, sizeof(scoreboard)); + scoreboard.last_waddr_add = ~0; + scoreboard.last_waddr_mul = ~0; + scoreboard.last_ldvary_tick = -10; + scoreboard.last_sfu_write_tick = -10; + scoreboard.last_uniforms_reset_tick = -10; + + if (debug) { + fprintf(stderr, "Pre-schedule instructions\n"); + vir_for_each_block(block, c) { + fprintf(stderr, "BLOCK %d\n", block->index); + list_for_each_entry(struct qinst, qinst, + &block->instructions, link) { + v3d_qpu_dump(devinfo, &qinst->qpu); + fprintf(stderr, "\n"); + } + } + fprintf(stderr, "\n"); + } + + uint32_t cycles = 0; + vir_for_each_block(block, c) { + block->start_qpu_ip = c->qpu_inst_count; + block->branch_qpu_ip = ~0; + block->start_uniform = next_uniform; + + cycles += qpu_schedule_instructions_block(c, + &scoreboard, + block, + uniform_contents, + uniform_data, + &next_uniform); + + block->end_qpu_ip = c->qpu_inst_count - 1; + } + + qpu_set_branch_targets(c); + + assert(next_uniform == c->num_uniforms); + + return cycles; +} diff --git a/lib/mesa/src/broadcom/compiler/qpu_validate.c b/lib/mesa/src/broadcom/compiler/qpu_validate.c new file mode 100644 index 000000000..d99d76a8b --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/qpu_validate.c @@ -0,0 +1,208 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/** + * @file + * + * Validates the QPU instruction sequence after register allocation and + * scheduling. + */ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include "v3d_compiler.h" +#include "qpu/qpu_disasm.h" + +struct v3d_qpu_validate_state { + struct v3d_compile *c; + const struct v3d_qpu_instr *last; + int ip; + int last_sfu_write; +}; + +static void +fail_instr(struct v3d_qpu_validate_state *state, const char *msg) +{ + struct v3d_compile *c = state->c; + + fprintf(stderr, "v3d_qpu_validate at ip %d: %s:\n", state->ip, msg); + + int dump_ip = 0; + vir_for_each_inst_inorder(inst, c) { + v3d_qpu_dump(c->devinfo, &inst->qpu); + + if (dump_ip++ == state->ip) + fprintf(stderr, " *** ERROR ***"); + + fprintf(stderr, "\n"); + } + + fprintf(stderr, "\n"); + abort(); +} + +static bool +qpu_magic_waddr_matches(const struct v3d_qpu_instr *inst, + bool (*predicate)(enum v3d_qpu_waddr waddr)) +{ + if (inst->type == V3D_QPU_INSTR_TYPE_ALU) + return false; + + if (inst->alu.add.op != V3D_QPU_A_NOP && + inst->alu.add.magic_write && + predicate(inst->alu.add.waddr)) + return true; + + if (inst->alu.mul.op != V3D_QPU_M_NOP && + inst->alu.mul.magic_write && + predicate(inst->alu.mul.waddr)) + return true; + + return false; +} + +static void +qpu_validate_inst(struct v3d_qpu_validate_state *state, struct qinst *qinst) +{ + const struct v3d_qpu_instr *inst = &qinst->qpu; + + if (inst->type != V3D_QPU_INSTR_TYPE_ALU) + return; + + /* LDVARY writes r5 two instructions later and LDUNIF writes + * r5 one instruction later, which is illegal to have + * together. + */ + if (state->last && state->last->sig.ldvary && inst->sig.ldunif) { + fail_instr(state, "LDUNIF after a LDVARY"); + } + + int tmu_writes = 0; + int sfu_writes = 0; + int vpm_writes = 0; + int tlb_writes = 0; + int tsy_writes = 0; + + if (inst->alu.add.op != V3D_QPU_A_NOP) { + if (inst->alu.add.magic_write) { + if (v3d_qpu_magic_waddr_is_tmu(inst->alu.add.waddr)) + tmu_writes++; + if (v3d_qpu_magic_waddr_is_sfu(inst->alu.add.waddr)) + sfu_writes++; + if (v3d_qpu_magic_waddr_is_vpm(inst->alu.add.waddr)) + vpm_writes++; + if (v3d_qpu_magic_waddr_is_tlb(inst->alu.add.waddr)) + tlb_writes++; + if (v3d_qpu_magic_waddr_is_tsy(inst->alu.add.waddr)) + tsy_writes++; + } + } + + if (inst->alu.mul.op != V3D_QPU_M_NOP) { + if (inst->alu.mul.magic_write) { + if (v3d_qpu_magic_waddr_is_tmu(inst->alu.mul.waddr)) + tmu_writes++; + if (v3d_qpu_magic_waddr_is_sfu(inst->alu.mul.waddr)) + sfu_writes++; + if (v3d_qpu_magic_waddr_is_vpm(inst->alu.mul.waddr)) + vpm_writes++; + if (v3d_qpu_magic_waddr_is_tlb(inst->alu.mul.waddr)) + tlb_writes++; + if (v3d_qpu_magic_waddr_is_tsy(inst->alu.mul.waddr)) + tsy_writes++; + } + } + + (void)qpu_magic_waddr_matches; /* XXX */ + + /* SFU r4 results come back two instructions later. No doing + * r4 read/writes or other SFU lookups until it's done. + */ + if (state->ip - state->last_sfu_write < 2) { + if (v3d_qpu_uses_mux(inst, V3D_QPU_MUX_R4)) + fail_instr(state, "R4 read too soon after SFU"); + + if (v3d_qpu_writes_r4(inst)) + fail_instr(state, "R4 write too soon after SFU"); + + if (sfu_writes) + fail_instr(state, "SFU write too soon after SFU"); + } + + /* XXX: The docs say VPM can happen with the others, but the simulator + * disagrees. + */ + if (tmu_writes + + sfu_writes + + vpm_writes + + tlb_writes + + tsy_writes + + inst->sig.ldtmu + + inst->sig.ldtlb + + inst->sig.ldvpm + + inst->sig.ldtlbu > 1) { + fail_instr(state, + "Only one of [TMU, SFU, TSY, TLB read, VPM] allowed"); + } + + if (sfu_writes) + state->last_sfu_write = state->ip; +} + +static void +qpu_validate_block(struct v3d_qpu_validate_state *state, struct qblock *block) +{ + vir_for_each_inst(qinst, block) { + qpu_validate_inst(state, qinst); + + state->last = &qinst->qpu; + state->ip++; + } +} + +/** + * Checks for the instruction restrictions from page 37 ("Summary of + * Instruction Restrictions"). + */ +void +qpu_validate(struct v3d_compile *c) +{ + /* We don't want to do validation in release builds, but we want to + * keep compiling the validation code to make sure it doesn't get + * broken. + */ +#ifndef DEBUG + return; +#endif + + struct v3d_qpu_validate_state state = { + .c = c, + .last_sfu_write = -10, + .ip = 0, + }; + + vir_for_each_block(block, c) { + qpu_validate_block(&state, block); + } +} diff --git a/lib/mesa/src/broadcom/compiler/v3d_compiler.h b/lib/mesa/src/broadcom/compiler/v3d_compiler.h new file mode 100644 index 000000000..021c88f7b --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/v3d_compiler.h @@ -0,0 +1,934 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 V3D_COMPILER_H +#define V3D_COMPILER_H + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <stdint.h> +#include <string.h> + +#include "util/macros.h" +#include "common/v3d_debug.h" +#include "compiler/nir/nir.h" +#include "util/list.h" +#include "util/u_math.h" + +#include "qpu/qpu_instr.h" +#include "pipe/p_state.h" + +#define V3D_MAX_TEXTURE_SAMPLERS 32 +#define V3D_MAX_SAMPLES 4 +#define V3D_MAX_FS_INPUTS 64 +#define V3D_MAX_VS_INPUTS 64 + +struct nir_builder; + +struct v3d_fs_inputs { + /** + * Array of the meanings of the VPM inputs this shader needs. + * + * It doesn't include those that aren't part of the VPM, like + * point/line coordinates. + */ + struct v3d_varying_slot *input_slots; + uint32_t num_inputs; +}; + +enum qfile { + /** An unused source or destination register. */ + QFILE_NULL, + + /** A physical register, such as the W coordinate payload. */ + QFILE_REG, + /** One of the regsiters for fixed function interactions. */ + QFILE_MAGIC, + + /** + * A virtual register, that will be allocated to actual accumulator + * or physical registers later. + */ + QFILE_TEMP, + QFILE_VARY, + QFILE_UNIF, + QFILE_TLB, + QFILE_TLBU, + + /** + * VPM reads use this with an index value to say what part of the VPM + * is being read. + */ + QFILE_VPM, + + /** + * Stores an immediate value in the index field that will be used + * directly by qpu_load_imm(). + */ + QFILE_LOAD_IMM, + + /** + * Stores an immediate value in the index field that can be turned + * into a small immediate field by qpu_encode_small_immediate(). + */ + QFILE_SMALL_IMM, +}; + +/** + * A reference to a QPU register or a virtual temp register. + */ +struct qreg { + enum qfile file; + uint32_t index; +}; + +static inline struct qreg vir_reg(enum qfile file, uint32_t index) +{ + return (struct qreg){file, index}; +} + +/** + * A reference to an actual register at the QPU level, for register + * allocation. + */ +struct qpu_reg { + bool magic; + int index; +}; + +struct qinst { + /** Entry in qblock->instructions */ + struct list_head link; + + /** + * The instruction being wrapped. Its condition codes, pack flags, + * signals, etc. will all be used, with just the register references + * being replaced by the contents of qinst->dst and qinst->src[]. + */ + struct v3d_qpu_instr qpu; + + /* Pre-register-allocation references to src/dst registers */ + struct qreg dst; + struct qreg src[3]; + bool cond_is_exec_mask; + bool has_implicit_uniform; + + /* After vir_to_qpu.c: If instr reads a uniform, which uniform from + * the uncompiled stream it is. + */ + int uniform; +}; + +enum quniform_contents { + /** + * Indicates that a constant 32-bit value is copied from the program's + * uniform contents. + */ + QUNIFORM_CONSTANT, + /** + * Indicates that the program's uniform contents are used as an index + * into the GL uniform storage. + */ + QUNIFORM_UNIFORM, + + /** @{ + * Scaling factors from clip coordinates to relative to the viewport + * center. + * + * This is used by the coordinate and vertex shaders to produce the + * 32-bit entry consisting of 2 16-bit fields with 12.4 signed fixed + * point offsets from the viewport ccenter. + */ + QUNIFORM_VIEWPORT_X_SCALE, + QUNIFORM_VIEWPORT_Y_SCALE, + /** @} */ + + QUNIFORM_VIEWPORT_Z_OFFSET, + QUNIFORM_VIEWPORT_Z_SCALE, + + QUNIFORM_USER_CLIP_PLANE, + + /** + * A reference to a texture config parameter 0 uniform. + * + * This is a uniform implicitly loaded with a QPU_W_TMU* write, which + * defines texture type, miplevels, and such. It will be found as a + * parameter to the first QOP_TEX_[STRB] instruction in a sequence. + */ + QUNIFORM_TEXTURE_CONFIG_P0_0, + QUNIFORM_TEXTURE_CONFIG_P0_1, + QUNIFORM_TEXTURE_CONFIG_P0_2, + QUNIFORM_TEXTURE_CONFIG_P0_3, + QUNIFORM_TEXTURE_CONFIG_P0_4, + QUNIFORM_TEXTURE_CONFIG_P0_5, + QUNIFORM_TEXTURE_CONFIG_P0_6, + QUNIFORM_TEXTURE_CONFIG_P0_7, + QUNIFORM_TEXTURE_CONFIG_P0_8, + QUNIFORM_TEXTURE_CONFIG_P0_9, + QUNIFORM_TEXTURE_CONFIG_P0_10, + QUNIFORM_TEXTURE_CONFIG_P0_11, + QUNIFORM_TEXTURE_CONFIG_P0_12, + QUNIFORM_TEXTURE_CONFIG_P0_13, + QUNIFORM_TEXTURE_CONFIG_P0_14, + QUNIFORM_TEXTURE_CONFIG_P0_15, + QUNIFORM_TEXTURE_CONFIG_P0_16, + QUNIFORM_TEXTURE_CONFIG_P0_17, + QUNIFORM_TEXTURE_CONFIG_P0_18, + QUNIFORM_TEXTURE_CONFIG_P0_19, + QUNIFORM_TEXTURE_CONFIG_P0_20, + QUNIFORM_TEXTURE_CONFIG_P0_21, + QUNIFORM_TEXTURE_CONFIG_P0_22, + QUNIFORM_TEXTURE_CONFIG_P0_23, + QUNIFORM_TEXTURE_CONFIG_P0_24, + QUNIFORM_TEXTURE_CONFIG_P0_25, + QUNIFORM_TEXTURE_CONFIG_P0_26, + QUNIFORM_TEXTURE_CONFIG_P0_27, + QUNIFORM_TEXTURE_CONFIG_P0_28, + QUNIFORM_TEXTURE_CONFIG_P0_29, + QUNIFORM_TEXTURE_CONFIG_P0_30, + QUNIFORM_TEXTURE_CONFIG_P0_31, + QUNIFORM_TEXTURE_CONFIG_P0_32, + + /** + * A reference to a texture config parameter 1 uniform. + * + * This is a uniform implicitly loaded with a QPU_W_TMU* write, which + * defines texture width, height, filters, and wrap modes. It will be + * found as a parameter to the second QOP_TEX_[STRB] instruction in a + * sequence. + */ + QUNIFORM_TEXTURE_CONFIG_P1, + + QUNIFORM_TEXTURE_FIRST_LEVEL, + + QUNIFORM_TEXTURE_WIDTH, + QUNIFORM_TEXTURE_HEIGHT, + QUNIFORM_TEXTURE_DEPTH, + QUNIFORM_TEXTURE_ARRAY_SIZE, + QUNIFORM_TEXTURE_LEVELS, + + QUNIFORM_TEXTURE_MSAA_ADDR, + + QUNIFORM_UBO_ADDR, + + QUNIFORM_TEXRECT_SCALE_X, + QUNIFORM_TEXRECT_SCALE_Y, + + QUNIFORM_TEXTURE_BORDER_COLOR, + + QUNIFORM_STENCIL, + + QUNIFORM_ALPHA_REF, + QUNIFORM_SAMPLE_MASK, +}; + +struct v3d_varying_slot { + uint8_t slot_and_component; +}; + +static inline struct v3d_varying_slot +v3d_slot_from_slot_and_component(uint8_t slot, uint8_t component) +{ + assert(slot < 255 / 4); + return (struct v3d_varying_slot){ (slot << 2) + component }; +} + +static inline uint8_t v3d_slot_get_slot(struct v3d_varying_slot slot) +{ + return slot.slot_and_component >> 2; +} + +static inline uint8_t v3d_slot_get_component(struct v3d_varying_slot slot) +{ + return slot.slot_and_component & 3; +} + +struct v3d_ubo_range { + /** + * offset in bytes from the start of the ubo where this range is + * uploaded. + * + * Only set once used is set. + */ + uint32_t dst_offset; + + /** + * offset in bytes from the start of the gallium uniforms where the + * data comes from. + */ + uint32_t src_offset; + + /** size in bytes of this ubo range */ + uint32_t size; +}; + +struct v3d_key { + void *shader_state; + struct { + uint8_t swizzle[4]; + uint8_t return_size; + uint8_t return_channels; + union { + struct { + unsigned compare_mode:1; + unsigned compare_func:3; + unsigned wrap_s:3; + unsigned wrap_t:3; + }; + struct { + uint16_t msaa_width, msaa_height; + }; + }; + } tex[V3D_MAX_TEXTURE_SAMPLERS]; + uint8_t ucp_enables; +}; + +struct v3d_fs_key { + struct v3d_key base; + bool depth_enabled; + bool is_points; + bool is_lines; + bool alpha_test; + bool point_coord_upper_left; + bool light_twoside; + bool msaa; + bool sample_coverage; + bool sample_alpha_to_coverage; + bool sample_alpha_to_one; + bool clamp_color; + uint8_t nr_cbufs; + uint8_t swap_color_rb; + /* Mask of which render targets need to be written as 32-bit floats */ + uint8_t f32_color_rb; + uint8_t alpha_test_func; + uint8_t logicop_func; + uint32_t point_sprite_mask; + + struct pipe_rt_blend_state blend; +}; + +struct v3d_vs_key { + struct v3d_key base; + + struct v3d_varying_slot fs_inputs[V3D_MAX_FS_INPUTS]; + uint8_t num_fs_inputs; + + bool is_coord; + bool per_vertex_point_size; + bool clamp_color; +}; + +/** A basic block of VIR intructions. */ +struct qblock { + struct list_head link; + + struct list_head instructions; + + struct set *predecessors; + struct qblock *successors[2]; + + int index; + + /* Instruction IPs for the first and last instruction of the block. + * Set by qpu_schedule.c. + */ + uint32_t start_qpu_ip; + uint32_t end_qpu_ip; + + /* Instruction IP for the branch instruction of the block. Set by + * qpu_schedule.c. + */ + uint32_t branch_qpu_ip; + + /** Offset within the uniform stream at the start of the block. */ + uint32_t start_uniform; + /** Offset within the uniform stream of the branch instruction */ + uint32_t branch_uniform; + + /** @{ used by v3d_vir_live_variables.c */ + BITSET_WORD *def; + BITSET_WORD *use; + BITSET_WORD *live_in; + BITSET_WORD *live_out; + int start_ip, end_ip; + /** @} */ +}; + +/** + * Compiler state saved across compiler invocations, for any expensive global + * setup. + */ +struct v3d_compiler { + const struct v3d_device_info *devinfo; + struct ra_regs *regs; + unsigned int reg_class[3]; +}; + +struct v3d_compile { + const struct v3d_device_info *devinfo; + nir_shader *s; + nir_function_impl *impl; + struct exec_list *cf_node_list; + const struct v3d_compiler *compiler; + + /** + * Mapping from nir_register * or nir_ssa_def * to array of struct + * qreg for the values. + */ + struct hash_table *def_ht; + + /* For each temp, the instruction generating its value. */ + struct qinst **defs; + uint32_t defs_array_size; + + /** + * Inputs to the shader, arranged by TGSI declaration order. + * + * Not all fragment shader QFILE_VARY reads are present in this array. + */ + struct qreg *inputs; + struct qreg *outputs; + bool msaa_per_sample_output; + struct qreg color_reads[V3D_MAX_SAMPLES]; + struct qreg sample_colors[V3D_MAX_SAMPLES]; + uint32_t inputs_array_size; + uint32_t outputs_array_size; + uint32_t uniforms_array_size; + + /* Booleans for whether the corresponding QFILE_VARY[i] is + * flat-shaded. This doesn't count gl_FragColor flat-shading, which is + * controlled by shader->color_inputs and rasterizer->flatshade in the + * gallium driver. + */ + BITSET_WORD flat_shade_flags[BITSET_WORDS(V3D_MAX_FS_INPUTS)]; + + /* Booleans for whether the corresponding QFILE_VARY[i] uses the + * default glShadeModel() behavior. + */ + BITSET_WORD shade_model_flags[BITSET_WORDS(V3D_MAX_FS_INPUTS)]; + + struct v3d_ubo_range *ubo_ranges; + bool *ubo_range_used; + uint32_t ubo_ranges_array_size; + /** Number of uniform areas tracked in ubo_ranges. */ + uint32_t num_ubo_ranges; + uint32_t next_ubo_dst_offset; + + /* State for whether we're executing on each channel currently. 0 if + * yes, otherwise a block number + 1 that the channel jumped to. + */ + struct qreg execute; + + struct qreg line_x, point_x, point_y; + + /** + * Instance ID, which comes in before the vertex attribute payload if + * the shader record requests it. + */ + struct qreg iid; + + /** + * Vertex ID, which comes in before the vertex attribute payload + * (after Instance ID) if the shader record requests it. + */ + struct qreg vid; + + /* Fragment shader payload regs. */ + struct qreg payload_w, payload_w_centroid, payload_z; + + uint8_t vattr_sizes[V3D_MAX_VS_INPUTS]; + uint32_t num_vpm_writes; + + /** + * Array of the VARYING_SLOT_* of all FS QFILE_VARY reads. + * + * This includes those that aren't part of the VPM varyings, like + * point/line coordinates. + */ + struct v3d_varying_slot input_slots[V3D_MAX_FS_INPUTS]; + + /** + * An entry per outputs[] in the VS indicating what the VARYING_SLOT_* + * of the output is. Used to emit from the VS in the order that the + * FS needs. + */ + struct v3d_varying_slot *output_slots; + + struct pipe_shader_state *shader_state; + struct v3d_key *key; + struct v3d_fs_key *fs_key; + struct v3d_vs_key *vs_key; + + /* Live ranges of temps. */ + int *temp_start, *temp_end; + + uint32_t *uniform_data; + enum quniform_contents *uniform_contents; + uint32_t uniform_array_size; + uint32_t num_uniforms; + uint32_t num_outputs; + uint32_t output_position_index; + nir_variable *output_color_var[4]; + uint32_t output_point_size_index; + uint32_t output_sample_mask_index; + + struct qreg undef; + uint32_t num_temps; + + struct list_head blocks; + int next_block_index; + struct qblock *cur_block; + struct qblock *loop_cont_block; + struct qblock *loop_break_block; + + uint64_t *qpu_insts; + uint32_t qpu_inst_count; + uint32_t qpu_inst_size; + + /* For the FS, the number of varying inputs not counting the + * point/line varyings payload + */ + uint32_t num_inputs; + + /** + * Number of inputs from num_inputs remaining to be queued to the read + * FIFO in the VS/CS. + */ + uint32_t num_inputs_remaining; + + /* Number of inputs currently in the read FIFO for the VS/CS */ + uint32_t num_inputs_in_fifo; + + /** Next offset in the VPM to read from in the VS/CS */ + uint32_t vpm_read_offset; + + uint32_t program_id; + uint32_t variant_id; + + /* Set to compile program in threaded FS mode, where SIG_THREAD_SWITCH + * is used to hide texturing latency at the cost of limiting ourselves + * to the bottom half of physical reg space. + */ + bool fs_threaded; + + bool last_thrsw_at_top_level; + + bool failed; +}; + +struct v3d_uniform_list { + enum quniform_contents *contents; + uint32_t *data; + uint32_t count; +}; + +struct v3d_prog_data { + struct v3d_uniform_list uniforms; + + struct v3d_ubo_range *ubo_ranges; + uint32_t num_ubo_ranges; + uint32_t ubo_size; + + uint8_t num_inputs; + +}; + +struct v3d_vs_prog_data { + struct v3d_prog_data base; + + bool uses_iid, uses_vid; + + /* Number of components read from each vertex attribute. */ + uint8_t vattr_sizes[32]; + + /* Total number of components read, for the shader state record. */ + uint32_t vpm_input_size; + + /* Total number of components written, for the shader state record. */ + uint32_t vpm_output_size; +}; + +struct v3d_fs_prog_data { + struct v3d_prog_data base; + + struct v3d_varying_slot input_slots[V3D_MAX_FS_INPUTS]; + + /* Bitmask for whether the corresponding input is flat-shaded, + * independent of rasterizer (gl_FragColor) flat-shading. + */ + BITSET_WORD flat_shade_flags[BITSET_WORDS(V3D_MAX_FS_INPUTS)]; + /* Bitmask for whether the corresponding input uses the default + * glShadeModel() behavior. + */ + BITSET_WORD shade_model_flags[BITSET_WORDS(V3D_MAX_FS_INPUTS)]; + + bool writes_z; + bool discard; +}; + +/* Special nir_load_input intrinsic index for loading the current TLB + * destination color. + */ +#define V3D_NIR_TLB_COLOR_READ_INPUT 2000000000 + +#define V3D_NIR_MS_MASK_OUTPUT 2000000000 + +extern const nir_shader_compiler_options v3d_nir_options; + +const struct v3d_compiler *v3d_compiler_init(const struct v3d_device_info *devinfo); +void v3d_compiler_free(const struct v3d_compiler *compiler); +void v3d_optimize_nir(struct nir_shader *s); + +uint64_t *v3d_compile_vs(const struct v3d_compiler *compiler, + struct v3d_vs_key *key, + struct v3d_vs_prog_data *prog_data, + nir_shader *s, + int program_id, int variant_id, + uint32_t *final_assembly_size); + +uint64_t *v3d_compile_fs(const struct v3d_compiler *compiler, + struct v3d_fs_key *key, + struct v3d_fs_prog_data *prog_data, + nir_shader *s, + int program_id, int variant_id, + uint32_t *final_assembly_size); + +void v3d_nir_to_vir(struct v3d_compile *c); + +void vir_compile_destroy(struct v3d_compile *c); +const char *vir_get_stage_name(struct v3d_compile *c); +struct qblock *vir_new_block(struct v3d_compile *c); +void vir_set_emit_block(struct v3d_compile *c, struct qblock *block); +void vir_link_blocks(struct qblock *predecessor, struct qblock *successor); +struct qblock *vir_entry_block(struct v3d_compile *c); +struct qblock *vir_exit_block(struct v3d_compile *c); +struct qinst *vir_add_inst(enum v3d_qpu_add_op op, struct qreg dst, + struct qreg src0, struct qreg src1); +struct qinst *vir_mul_inst(enum v3d_qpu_mul_op op, struct qreg dst, + struct qreg src0, struct qreg src1); +struct qinst *vir_branch_inst(enum v3d_qpu_branch_cond cond, struct qreg src0); +void vir_remove_instruction(struct v3d_compile *c, struct qinst *qinst); +struct qreg vir_uniform(struct v3d_compile *c, + enum quniform_contents contents, + uint32_t data); +void vir_schedule_instructions(struct v3d_compile *c); +struct v3d_qpu_instr v3d_qpu_nop(void); + +struct qreg vir_emit_def(struct v3d_compile *c, struct qinst *inst); +struct qinst *vir_emit_nondef(struct v3d_compile *c, struct qinst *inst); +void vir_set_cond(struct qinst *inst, enum v3d_qpu_cond cond); +void vir_set_pf(struct qinst *inst, enum v3d_qpu_pf pf); +void vir_set_unpack(struct qinst *inst, int src, + enum v3d_qpu_input_unpack unpack); + +struct qreg vir_get_temp(struct v3d_compile *c); +void vir_calculate_live_intervals(struct v3d_compile *c); +bool vir_has_implicit_uniform(struct qinst *inst); +int vir_get_implicit_uniform_src(struct qinst *inst); +int vir_get_non_sideband_nsrc(struct qinst *inst); +int vir_get_nsrc(struct qinst *inst); +bool vir_has_side_effects(struct v3d_compile *c, struct qinst *inst); +bool vir_get_add_op(struct qinst *inst, enum v3d_qpu_add_op *op); +bool vir_get_mul_op(struct qinst *inst, enum v3d_qpu_mul_op *op); +bool vir_is_raw_mov(struct qinst *inst); +bool vir_is_tex(struct qinst *inst); +bool vir_is_add(struct qinst *inst); +bool vir_is_mul(struct qinst *inst); +bool vir_is_float_input(struct qinst *inst); +bool vir_depends_on_flags(struct qinst *inst); +bool vir_writes_r3(struct qinst *inst); +bool vir_writes_r4(struct qinst *inst); +struct qreg vir_follow_movs(struct v3d_compile *c, struct qreg reg); +uint8_t vir_channels_written(struct qinst *inst); + +void vir_dump(struct v3d_compile *c); +void vir_dump_inst(struct v3d_compile *c, struct qinst *inst); + +void vir_validate(struct v3d_compile *c); + +void vir_optimize(struct v3d_compile *c); +bool vir_opt_algebraic(struct v3d_compile *c); +bool vir_opt_constant_folding(struct v3d_compile *c); +bool vir_opt_copy_propagate(struct v3d_compile *c); +bool vir_opt_dead_code(struct v3d_compile *c); +bool vir_opt_peephole_sf(struct v3d_compile *c); +bool vir_opt_small_immediates(struct v3d_compile *c); +bool vir_opt_vpm(struct v3d_compile *c); +void v3d_nir_lower_blend(nir_shader *s, struct v3d_compile *c); +void v3d_nir_lower_io(nir_shader *s, struct v3d_compile *c); +void v3d_nir_lower_txf_ms(nir_shader *s, struct v3d_compile *c); +void vir_lower_uniforms(struct v3d_compile *c); + +void v3d_vir_to_qpu(struct v3d_compile *c); +uint32_t v3d_qpu_schedule_instructions(struct v3d_compile *c); +void qpu_validate(struct v3d_compile *c); +struct qpu_reg *v3d_register_allocate(struct v3d_compile *c); +bool vir_init_reg_sets(struct v3d_compiler *compiler); + +void vir_PF(struct v3d_compile *c, struct qreg src, enum v3d_qpu_pf pf); + +static inline bool +quniform_contents_is_texture_p0(enum quniform_contents contents) +{ + return (contents >= QUNIFORM_TEXTURE_CONFIG_P0_0 && + contents < (QUNIFORM_TEXTURE_CONFIG_P0_0 + + V3D_MAX_TEXTURE_SAMPLERS)); +} + +static inline struct qreg +vir_uniform_ui(struct v3d_compile *c, uint32_t ui) +{ + return vir_uniform(c, QUNIFORM_CONSTANT, ui); +} + +static inline struct qreg +vir_uniform_f(struct v3d_compile *c, float f) +{ + return vir_uniform(c, QUNIFORM_CONSTANT, fui(f)); +} + +#define VIR_ALU0(name, vir_inst, op) \ +static inline struct qreg \ +vir_##name(struct v3d_compile *c) \ +{ \ + return vir_emit_def(c, vir_inst(op, c->undef, \ + c->undef, c->undef)); \ +} \ +static inline struct qinst * \ +vir_##name##_dest(struct v3d_compile *c, struct qreg dest) \ +{ \ + return vir_emit_nondef(c, vir_inst(op, dest, \ + c->undef, c->undef)); \ +} + +#define VIR_ALU1(name, vir_inst, op) \ +static inline struct qreg \ +vir_##name(struct v3d_compile *c, struct qreg a) \ +{ \ + return vir_emit_def(c, vir_inst(op, c->undef, \ + a, c->undef)); \ +} \ +static inline struct qinst * \ +vir_##name##_dest(struct v3d_compile *c, struct qreg dest, \ + struct qreg a) \ +{ \ + return vir_emit_nondef(c, vir_inst(op, dest, a, \ + c->undef)); \ +} + +#define VIR_ALU2(name, vir_inst, op) \ +static inline struct qreg \ +vir_##name(struct v3d_compile *c, struct qreg a, struct qreg b) \ +{ \ + return vir_emit_def(c, vir_inst(op, c->undef, a, b)); \ +} \ +static inline struct qinst * \ +vir_##name##_dest(struct v3d_compile *c, struct qreg dest, \ + struct qreg a, struct qreg b) \ +{ \ + return vir_emit_nondef(c, vir_inst(op, dest, a, b)); \ +} + +#define VIR_NODST_1(name, vir_inst, op) \ +static inline struct qinst * \ +vir_##name(struct v3d_compile *c, struct qreg a) \ +{ \ + return vir_emit_nondef(c, vir_inst(op, c->undef, \ + a, c->undef)); \ +} + +#define VIR_NODST_2(name, vir_inst, op) \ +static inline struct qinst * \ +vir_##name(struct v3d_compile *c, struct qreg a, struct qreg b) \ +{ \ + return vir_emit_nondef(c, vir_inst(op, c->undef, \ + a, b)); \ +} + +#define VIR_A_ALU2(name) VIR_ALU2(name, vir_add_inst, V3D_QPU_A_##name) +#define VIR_M_ALU2(name) VIR_ALU2(name, vir_mul_inst, V3D_QPU_M_##name) +#define VIR_A_ALU1(name) VIR_ALU1(name, vir_add_inst, V3D_QPU_A_##name) +#define VIR_M_ALU1(name) VIR_ALU1(name, vir_mul_inst, V3D_QPU_M_##name) +#define VIR_A_ALU0(name) VIR_ALU0(name, vir_add_inst, V3D_QPU_A_##name) +#define VIR_M_ALU0(name) VIR_ALU0(name, vir_mul_inst, V3D_QPU_M_##name) +#define VIR_A_NODST_2(name) VIR_NODST_2(name, vir_add_inst, V3D_QPU_A_##name) +#define VIR_M_NODST_2(name) VIR_NODST_2(name, vir_mul_inst, V3D_QPU_M_##name) +#define VIR_A_NODST_1(name) VIR_NODST_1(name, vir_add_inst, V3D_QPU_A_##name) +#define VIR_M_NODST_1(name) VIR_NODST_1(name, vir_mul_inst, V3D_QPU_M_##name) + +VIR_A_ALU2(FADD) +VIR_A_ALU2(VFPACK) +VIR_A_ALU2(FSUB) +VIR_A_ALU2(FMIN) +VIR_A_ALU2(FMAX) + +VIR_A_ALU2(ADD) +VIR_A_ALU2(SUB) +VIR_A_ALU2(SHL) +VIR_A_ALU2(SHR) +VIR_A_ALU2(ASR) +VIR_A_ALU2(ROR) +VIR_A_ALU2(MIN) +VIR_A_ALU2(MAX) +VIR_A_ALU2(UMIN) +VIR_A_ALU2(UMAX) +VIR_A_ALU2(AND) +VIR_A_ALU2(OR) +VIR_A_ALU2(XOR) +VIR_A_ALU2(VADD) +VIR_A_ALU2(VSUB) +VIR_A_ALU1(NOT) +VIR_A_ALU1(NEG) +VIR_A_ALU1(FLAPUSH) +VIR_A_ALU1(FLBPUSH) +VIR_A_ALU1(FLBPOP) +VIR_A_ALU1(SETMSF) +VIR_A_ALU1(SETREVF) +VIR_A_ALU1(TIDX) +VIR_A_ALU1(EIDX) + +VIR_A_ALU0(FXCD) +VIR_A_ALU0(XCD) +VIR_A_ALU0(FYCD) +VIR_A_ALU0(YCD) +VIR_A_ALU0(MSF) +VIR_A_ALU0(REVF) +VIR_A_NODST_1(VPMSETUP) +VIR_A_ALU2(FCMP) +VIR_A_ALU2(VFMAX) + +VIR_A_ALU1(FROUND) +VIR_A_ALU1(FTOIN) +VIR_A_ALU1(FTRUNC) +VIR_A_ALU1(FTOIZ) +VIR_A_ALU1(FFLOOR) +VIR_A_ALU1(FTOUZ) +VIR_A_ALU1(FCEIL) +VIR_A_ALU1(FTOC) + +VIR_A_ALU1(FDX) +VIR_A_ALU1(FDY) + +VIR_A_ALU1(ITOF) +VIR_A_ALU1(CLZ) +VIR_A_ALU1(UTOF) + +VIR_M_ALU2(UMUL24) +VIR_M_ALU2(FMUL) +VIR_M_ALU2(SMUL24) +VIR_M_NODST_2(MULTOP) + +VIR_M_ALU1(MOV) +VIR_M_ALU1(FMOV) + +static inline struct qinst * +vir_MOV_cond(struct v3d_compile *c, enum v3d_qpu_cond cond, + struct qreg dest, struct qreg src) +{ + struct qinst *mov = vir_MOV_dest(c, dest, src); + vir_set_cond(mov, cond); + return mov; +} + +static inline struct qreg +vir_SEL(struct v3d_compile *c, enum v3d_qpu_cond cond, + struct qreg src0, struct qreg src1) +{ + struct qreg t = vir_get_temp(c); + vir_MOV_dest(c, t, src1); + vir_MOV_cond(c, cond, t, src0); + return t; +} + +static inline void +vir_VPM_WRITE(struct v3d_compile *c, struct qreg val) +{ + vir_MOV_dest(c, vir_reg(QFILE_MAGIC, V3D_QPU_WADDR_VPM), val); +} + +static inline struct qinst * +vir_NOP(struct v3d_compile *c) +{ + return vir_emit_nondef(c, vir_add_inst(V3D_QPU_A_NOP, + c->undef, c->undef, c->undef)); +} +/* +static inline struct qreg +vir_LOAD_IMM(struct v3d_compile *c, uint32_t val) +{ + return vir_emit_def(c, vir_inst(QOP_LOAD_IMM, c->undef, + vir_reg(QFILE_LOAD_IMM, val), c->undef)); +} + +static inline struct qreg +vir_LOAD_IMM_U2(struct v3d_compile *c, uint32_t val) +{ + return vir_emit_def(c, vir_inst(QOP_LOAD_IMM_U2, c->undef, + vir_reg(QFILE_LOAD_IMM, val), + c->undef)); +} +static inline struct qreg +vir_LOAD_IMM_I2(struct v3d_compile *c, uint32_t val) +{ + return vir_emit_def(c, vir_inst(QOP_LOAD_IMM_I2, c->undef, + vir_reg(QFILE_LOAD_IMM, val), + c->undef)); +} +*/ + +static inline struct qinst * +vir_BRANCH(struct v3d_compile *c, enum v3d_qpu_cond cond) +{ + /* The actual uniform_data value will be set at scheduling time */ + return vir_emit_nondef(c, vir_branch_inst(cond, vir_uniform_ui(c, 0))); +} + +#define vir_for_each_block(block, c) \ + list_for_each_entry(struct qblock, block, &c->blocks, link) + +#define vir_for_each_block_rev(block, c) \ + list_for_each_entry_rev(struct qblock, block, &c->blocks, link) + +/* Loop over the non-NULL members of the successors array. */ +#define vir_for_each_successor(succ, block) \ + for (struct qblock *succ = block->successors[0]; \ + succ != NULL; \ + succ = (succ == block->successors[1] ? NULL : \ + block->successors[1])) + +#define vir_for_each_inst(inst, block) \ + list_for_each_entry(struct qinst, inst, &block->instructions, link) + +#define vir_for_each_inst_rev(inst, block) \ + list_for_each_entry_rev(struct qinst, inst, &block->instructions, link) + +#define vir_for_each_inst_safe(inst, block) \ + list_for_each_entry_safe(struct qinst, inst, &block->instructions, link) + +#define vir_for_each_inst_inorder(inst, c) \ + vir_for_each_block(_block, c) \ + vir_for_each_inst(inst, _block) + +#endif /* V3D_COMPILER_H */ diff --git a/lib/mesa/src/broadcom/compiler/v3d_nir_lower_io.c b/lib/mesa/src/broadcom/compiler/v3d_nir_lower_io.c new file mode 100644 index 000000000..9cdcc0219 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/v3d_nir_lower_io.c @@ -0,0 +1,176 @@ +/* + * Copyright © 2015 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "compiler/v3d_compiler.h" +#include "compiler/nir/nir_builder.h" + +/** + * Walks the NIR generated by TGSI-to-NIR or GLSL-to-NIR to lower its io + * intrinsics into something amenable to the V3D architecture. + * + * Currently, it splits VS inputs and uniforms into scalars, drops any + * non-position outputs in coordinate shaders, and fixes up the addressing on + * indirect uniform loads. FS input and VS output scalarization is handled by + * nir_lower_io_to_scalar(). + */ + +static void +replace_intrinsic_with_vec(nir_builder *b, nir_intrinsic_instr *intr, + nir_ssa_def **comps) +{ + + /* Batch things back together into a vector. This will get split by + * the later ALU scalarization pass. + */ + nir_ssa_def *vec = nir_vec(b, comps, intr->num_components); + + /* Replace the old intrinsic with a reference to our reconstructed + * vector. + */ + nir_ssa_def_rewrite_uses(&intr->dest.ssa, nir_src_for_ssa(vec)); + nir_instr_remove(&intr->instr); +} + +static void +v3d_nir_lower_output(struct v3d_compile *c, nir_builder *b, + nir_intrinsic_instr *intr) +{ + nir_variable *output_var = NULL; + nir_foreach_variable(var, &c->s->outputs) { + if (var->data.driver_location == nir_intrinsic_base(intr)) { + output_var = var; + break; + } + } + assert(output_var); + + if (c->vs_key) { + int slot = output_var->data.location; + bool used = false; + + switch (slot) { + case VARYING_SLOT_PSIZ: + case VARYING_SLOT_POS: + used = true; + break; + + default: + for (int i = 0; i < c->vs_key->num_fs_inputs; i++) { + if (v3d_slot_get_slot(c->vs_key->fs_inputs[i]) == slot) { + used = true; + break; + } + } + break; + } + + if (!used) + nir_instr_remove(&intr->instr); + } +} + +static void +v3d_nir_lower_uniform(struct v3d_compile *c, nir_builder *b, + nir_intrinsic_instr *intr) +{ + b->cursor = nir_before_instr(&intr->instr); + + /* Generate scalar loads equivalent to the original vector. */ + nir_ssa_def *dests[4]; + for (unsigned i = 0; i < intr->num_components; i++) { + nir_intrinsic_instr *intr_comp = + nir_intrinsic_instr_create(c->s, intr->intrinsic); + intr_comp->num_components = 1; + nir_ssa_dest_init(&intr_comp->instr, &intr_comp->dest, 1, 32, NULL); + + /* Convert the uniform offset to bytes. If it happens + * to be a constant, constant-folding will clean up + * the shift for us. + */ + nir_intrinsic_set_base(intr_comp, + nir_intrinsic_base(intr) * 16 + + i * 4); + + intr_comp->src[0] = + nir_src_for_ssa(nir_ishl(b, intr->src[0].ssa, + nir_imm_int(b, 4))); + + dests[i] = &intr_comp->dest.ssa; + + nir_builder_instr_insert(b, &intr_comp->instr); + } + + replace_intrinsic_with_vec(b, intr, dests); +} + +static void +v3d_nir_lower_io_instr(struct v3d_compile *c, nir_builder *b, + struct nir_instr *instr) +{ + if (instr->type != nir_instr_type_intrinsic) + return; + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + + switch (intr->intrinsic) { + case nir_intrinsic_load_input: + break; + + case nir_intrinsic_store_output: + v3d_nir_lower_output(c, b, intr); + break; + + case nir_intrinsic_load_uniform: + v3d_nir_lower_uniform(c, b, intr); + break; + + case nir_intrinsic_load_user_clip_plane: + default: + break; + } +} + +static bool +v3d_nir_lower_io_impl(struct v3d_compile *c, nir_function_impl *impl) +{ + nir_builder b; + nir_builder_init(&b, impl); + + nir_foreach_block(block, impl) { + nir_foreach_instr_safe(instr, block) + v3d_nir_lower_io_instr(c, &b, instr); + } + + nir_metadata_preserve(impl, nir_metadata_block_index | + nir_metadata_dominance); + + return true; +} + +void +v3d_nir_lower_io(nir_shader *s, struct v3d_compile *c) +{ + nir_foreach_function(function, s) { + if (function->impl) + v3d_nir_lower_io_impl(c, function->impl); + } +} diff --git a/lib/mesa/src/broadcom/compiler/vir.c b/lib/mesa/src/broadcom/compiler/vir.c new file mode 100644 index 000000000..99b31841b --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/vir.c @@ -0,0 +1,898 @@ +/* + * Copyright © 2016-2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "v3d_compiler.h" + +int +vir_get_non_sideband_nsrc(struct qinst *inst) +{ + switch (inst->qpu.type) { + case V3D_QPU_INSTR_TYPE_BRANCH: + return 0; + case V3D_QPU_INSTR_TYPE_ALU: + if (inst->qpu.alu.add.op != V3D_QPU_A_NOP) + return v3d_qpu_add_op_num_src(inst->qpu.alu.add.op); + else + return v3d_qpu_mul_op_num_src(inst->qpu.alu.mul.op); + } + + return 0; +} + +int +vir_get_nsrc(struct qinst *inst) +{ + int nsrc = vir_get_non_sideband_nsrc(inst); + + if (vir_has_implicit_uniform(inst)) + nsrc++; + + return nsrc; +} + +bool +vir_has_implicit_uniform(struct qinst *inst) +{ + switch (inst->qpu.type) { + case V3D_QPU_INSTR_TYPE_BRANCH: + return true; + case V3D_QPU_INSTR_TYPE_ALU: + switch (inst->dst.file) { + case QFILE_TLBU: + return true; + default: + return inst->has_implicit_uniform; + } + } + return false; +} + +/* The sideband uniform for textures gets stored after the normal ALU + * arguments. + */ +int +vir_get_implicit_uniform_src(struct qinst *inst) +{ + return vir_get_nsrc(inst) - 1; +} + +/** + * Returns whether the instruction has any side effects that must be + * preserved. + */ +bool +vir_has_side_effects(struct v3d_compile *c, struct qinst *inst) +{ + switch (inst->qpu.type) { + case V3D_QPU_INSTR_TYPE_BRANCH: + return true; + case V3D_QPU_INSTR_TYPE_ALU: + switch (inst->qpu.alu.add.op) { + case V3D_QPU_A_SETREVF: + case V3D_QPU_A_SETMSF: + case V3D_QPU_A_VPMSETUP: + return true; + default: + break; + } + + switch (inst->qpu.alu.mul.op) { + case V3D_QPU_M_MULTOP: + return true; + default: + break; + } + } + + if (inst->qpu.sig.ldtmu) + return true; + + return false; +} + +bool +vir_is_float_input(struct qinst *inst) +{ + /* XXX: More instrs */ + switch (inst->qpu.type) { + case V3D_QPU_INSTR_TYPE_BRANCH: + return false; + case V3D_QPU_INSTR_TYPE_ALU: + switch (inst->qpu.alu.add.op) { + case V3D_QPU_A_FADD: + case V3D_QPU_A_FSUB: + case V3D_QPU_A_FMIN: + case V3D_QPU_A_FMAX: + case V3D_QPU_A_FTOIN: + return true; + default: + break; + } + + switch (inst->qpu.alu.mul.op) { + case V3D_QPU_M_FMOV: + case V3D_QPU_M_VFMUL: + case V3D_QPU_M_FMUL: + return true; + default: + break; + } + } + + return false; +} + +bool +vir_is_raw_mov(struct qinst *inst) +{ + if (inst->qpu.type != V3D_QPU_INSTR_TYPE_ALU || + (inst->qpu.alu.mul.op != V3D_QPU_M_FMOV && + inst->qpu.alu.mul.op != V3D_QPU_M_MOV)) { + return false; + } + + if (inst->qpu.alu.add.output_pack != V3D_QPU_PACK_NONE || + inst->qpu.alu.mul.output_pack != V3D_QPU_PACK_NONE) { + return false; + } + + if (inst->qpu.flags.ac != V3D_QPU_COND_NONE || + inst->qpu.flags.mc != V3D_QPU_COND_NONE) + return false; + + return true; +} + +bool +vir_is_add(struct qinst *inst) +{ + return (inst->qpu.type == V3D_QPU_INSTR_TYPE_ALU && + inst->qpu.alu.add.op != V3D_QPU_A_NOP); +} + +bool +vir_is_mul(struct qinst *inst) +{ + return (inst->qpu.type == V3D_QPU_INSTR_TYPE_ALU && + inst->qpu.alu.mul.op != V3D_QPU_M_NOP); +} + +bool +vir_is_tex(struct qinst *inst) +{ + if (inst->dst.file == QFILE_MAGIC) + return v3d_qpu_magic_waddr_is_tmu(inst->dst.index); + + return false; +} + +bool +vir_depends_on_flags(struct qinst *inst) +{ + if (inst->qpu.type == V3D_QPU_INSTR_TYPE_BRANCH) { + return (inst->qpu.branch.cond != V3D_QPU_BRANCH_COND_ALWAYS); + } else { + return (inst->qpu.flags.ac != V3D_QPU_COND_NONE && + inst->qpu.flags.mc != V3D_QPU_COND_NONE); + } +} + +bool +vir_writes_r3(struct qinst *inst) +{ + for (int i = 0; i < vir_get_nsrc(inst); i++) { + switch (inst->src[i].file) { + case QFILE_VARY: + case QFILE_VPM: + return true; + default: + break; + } + } + + return false; +} + +bool +vir_writes_r4(struct qinst *inst) +{ + switch (inst->dst.file) { + case QFILE_MAGIC: + switch (inst->dst.index) { + case V3D_QPU_WADDR_RECIP: + case V3D_QPU_WADDR_RSQRT: + case V3D_QPU_WADDR_EXP: + case V3D_QPU_WADDR_LOG: + case V3D_QPU_WADDR_SIN: + return true; + } + break; + default: + break; + } + + if (inst->qpu.sig.ldtmu) + return true; + + return false; +} + +void +vir_set_unpack(struct qinst *inst, int src, + enum v3d_qpu_input_unpack unpack) +{ + assert(src == 0 || src == 1); + + if (vir_is_add(inst)) { + if (src == 0) + inst->qpu.alu.add.a_unpack = unpack; + else + inst->qpu.alu.add.b_unpack = unpack; + } else { + assert(vir_is_mul(inst)); + if (src == 0) + inst->qpu.alu.mul.a_unpack = unpack; + else + inst->qpu.alu.mul.b_unpack = unpack; + } +} + +void +vir_set_cond(struct qinst *inst, enum v3d_qpu_cond cond) +{ + if (vir_is_add(inst)) { + inst->qpu.flags.ac = cond; + } else { + assert(vir_is_mul(inst)); + inst->qpu.flags.mc = cond; + } +} + +void +vir_set_pf(struct qinst *inst, enum v3d_qpu_pf pf) +{ + if (vir_is_add(inst)) { + inst->qpu.flags.apf = pf; + } else { + assert(vir_is_mul(inst)); + inst->qpu.flags.mpf = pf; + } +} + +#if 0 +uint8_t +vir_channels_written(struct qinst *inst) +{ + if (vir_is_mul(inst)) { + switch (inst->dst.pack) { + case QPU_PACK_MUL_NOP: + case QPU_PACK_MUL_8888: + return 0xf; + case QPU_PACK_MUL_8A: + return 0x1; + case QPU_PACK_MUL_8B: + return 0x2; + case QPU_PACK_MUL_8C: + return 0x4; + case QPU_PACK_MUL_8D: + return 0x8; + } + } else { + switch (inst->dst.pack) { + case QPU_PACK_A_NOP: + case QPU_PACK_A_8888: + case QPU_PACK_A_8888_SAT: + case QPU_PACK_A_32_SAT: + return 0xf; + case QPU_PACK_A_8A: + case QPU_PACK_A_8A_SAT: + return 0x1; + case QPU_PACK_A_8B: + case QPU_PACK_A_8B_SAT: + return 0x2; + case QPU_PACK_A_8C: + case QPU_PACK_A_8C_SAT: + return 0x4; + case QPU_PACK_A_8D: + case QPU_PACK_A_8D_SAT: + return 0x8; + case QPU_PACK_A_16A: + case QPU_PACK_A_16A_SAT: + return 0x3; + case QPU_PACK_A_16B: + case QPU_PACK_A_16B_SAT: + return 0xc; + } + } + unreachable("Bad pack field"); +} +#endif + +struct qreg +vir_get_temp(struct v3d_compile *c) +{ + struct qreg reg; + + reg.file = QFILE_TEMP; + reg.index = c->num_temps++; + + if (c->num_temps > c->defs_array_size) { + uint32_t old_size = c->defs_array_size; + c->defs_array_size = MAX2(old_size * 2, 16); + c->defs = reralloc(c, c->defs, struct qinst *, + c->defs_array_size); + memset(&c->defs[old_size], 0, + sizeof(c->defs[0]) * (c->defs_array_size - old_size)); + } + + return reg; +} + +struct qinst * +vir_add_inst(enum v3d_qpu_add_op op, struct qreg dst, struct qreg src0, struct qreg src1) +{ + struct qinst *inst = calloc(1, sizeof(*inst)); + + inst->qpu = v3d_qpu_nop(); + inst->qpu.alu.add.op = op; + + inst->dst = dst; + inst->src[0] = src0; + inst->src[1] = src1; + inst->uniform = ~0; + + return inst; +} + +struct qinst * +vir_mul_inst(enum v3d_qpu_mul_op op, struct qreg dst, struct qreg src0, struct qreg src1) +{ + struct qinst *inst = calloc(1, sizeof(*inst)); + + inst->qpu = v3d_qpu_nop(); + inst->qpu.alu.mul.op = op; + + inst->dst = dst; + inst->src[0] = src0; + inst->src[1] = src1; + inst->uniform = ~0; + + return inst; +} + +struct qinst * +vir_branch_inst(enum v3d_qpu_branch_cond cond, struct qreg src) +{ + struct qinst *inst = calloc(1, sizeof(*inst)); + + inst->qpu = v3d_qpu_nop(); + inst->qpu.type = V3D_QPU_INSTR_TYPE_BRANCH; + inst->qpu.branch.cond = cond; + inst->qpu.branch.msfign = V3D_QPU_MSFIGN_NONE; + inst->qpu.branch.bdi = V3D_QPU_BRANCH_DEST_REL; + inst->qpu.branch.ub = true; + inst->qpu.branch.bdu = V3D_QPU_BRANCH_DEST_REL; + + inst->dst = vir_reg(QFILE_NULL, 0); + inst->src[0] = src; + inst->uniform = ~0; + + return inst; +} + +static void +vir_emit(struct v3d_compile *c, struct qinst *inst) +{ + list_addtail(&inst->link, &c->cur_block->instructions); + + if (inst->dst.file == QFILE_MAGIC && + inst->dst.index == V3D_QPU_WADDR_VPM) + c->num_vpm_writes++; +} + +/* Updates inst to write to a new temporary, emits it, and notes the def. */ +struct qreg +vir_emit_def(struct v3d_compile *c, struct qinst *inst) +{ + assert(inst->dst.file == QFILE_NULL); + + inst->dst = vir_get_temp(c); + + if (inst->dst.file == QFILE_TEMP) + c->defs[inst->dst.index] = inst; + + vir_emit(c, inst); + + return inst->dst; +} + +struct qinst * +vir_emit_nondef(struct v3d_compile *c, struct qinst *inst) +{ + if (inst->dst.file == QFILE_TEMP) + c->defs[inst->dst.index] = NULL; + + vir_emit(c, inst); + + return inst; +} + +struct qblock * +vir_new_block(struct v3d_compile *c) +{ + struct qblock *block = rzalloc(c, struct qblock); + + list_inithead(&block->instructions); + + block->predecessors = _mesa_set_create(block, + _mesa_hash_pointer, + _mesa_key_pointer_equal); + + block->index = c->next_block_index++; + + return block; +} + +void +vir_set_emit_block(struct v3d_compile *c, struct qblock *block) +{ + c->cur_block = block; + list_addtail(&block->link, &c->blocks); +} + +struct qblock * +vir_entry_block(struct v3d_compile *c) +{ + return list_first_entry(&c->blocks, struct qblock, link); +} + +struct qblock * +vir_exit_block(struct v3d_compile *c) +{ + return list_last_entry(&c->blocks, struct qblock, link); +} + +void +vir_link_blocks(struct qblock *predecessor, struct qblock *successor) +{ + _mesa_set_add(successor->predecessors, predecessor); + if (predecessor->successors[0]) { + assert(!predecessor->successors[1]); + predecessor->successors[1] = successor; + } else { + predecessor->successors[0] = successor; + } +} + +const struct v3d_compiler * +v3d_compiler_init(const struct v3d_device_info *devinfo) +{ + struct v3d_compiler *compiler = rzalloc(NULL, struct v3d_compiler); + if (!compiler) + return NULL; + + compiler->devinfo = devinfo; + + if (!vir_init_reg_sets(compiler)) { + ralloc_free(compiler); + return NULL; + } + + return compiler; +} + +void +v3d_compiler_free(const struct v3d_compiler *compiler) +{ + ralloc_free((void *)compiler); +} + +static struct v3d_compile * +vir_compile_init(const struct v3d_compiler *compiler, + struct v3d_key *key, + nir_shader *s, + int program_id, int variant_id) +{ + struct v3d_compile *c = rzalloc(NULL, struct v3d_compile); + + c->compiler = compiler; + c->devinfo = compiler->devinfo; + c->key = key; + c->program_id = program_id; + c->variant_id = variant_id; + + s = nir_shader_clone(c, s); + c->s = s; + + list_inithead(&c->blocks); + vir_set_emit_block(c, vir_new_block(c)); + + c->output_position_index = -1; + c->output_point_size_index = -1; + c->output_sample_mask_index = -1; + + c->def_ht = _mesa_hash_table_create(c, _mesa_hash_pointer, + _mesa_key_pointer_equal); + + return c; +} + +static void +v3d_lower_nir(struct v3d_compile *c) +{ + struct nir_lower_tex_options tex_options = { + .lower_rect = false, /* XXX */ + .lower_txp = ~0, + /* Apply swizzles to all samplers. */ + .swizzle_result = ~0, + }; + + /* Lower the format swizzle and (for 32-bit returns) + * ARB_texture_swizzle-style swizzle. + */ + for (int i = 0; i < ARRAY_SIZE(c->key->tex); i++) { + for (int j = 0; j < 4; j++) + tex_options.swizzles[i][j] = c->key->tex[i].swizzle[j]; + } + + NIR_PASS_V(c->s, nir_lower_tex, &tex_options); +} + +static void +v3d_lower_nir_late(struct v3d_compile *c) +{ + NIR_PASS_V(c->s, v3d_nir_lower_io, c); + NIR_PASS_V(c->s, nir_lower_idiv); +} + +static void +v3d_set_prog_data_uniforms(struct v3d_compile *c, + struct v3d_prog_data *prog_data) +{ + int count = c->num_uniforms; + struct v3d_uniform_list *ulist = &prog_data->uniforms; + + ulist->count = count; + ulist->data = ralloc_array(prog_data, uint32_t, count); + memcpy(ulist->data, c->uniform_data, + count * sizeof(*ulist->data)); + ulist->contents = ralloc_array(prog_data, enum quniform_contents, count); + memcpy(ulist->contents, c->uniform_contents, + count * sizeof(*ulist->contents)); +} + +/* Copy the compiler UBO range state to the compiled shader, dropping out + * arrays that were never referenced by an indirect load. + * + * (Note that QIR dead code elimination of an array access still leaves that + * array alive, though) + */ +static void +v3d_set_prog_data_ubo(struct v3d_compile *c, + struct v3d_prog_data *prog_data) +{ + if (!c->num_ubo_ranges) + return; + + prog_data->num_ubo_ranges = 0; + prog_data->ubo_ranges = ralloc_array(prog_data, struct v3d_ubo_range, + c->num_ubo_ranges); + for (int i = 0; i < c->num_ubo_ranges; i++) { + if (!c->ubo_range_used[i]) + continue; + + struct v3d_ubo_range *range = &c->ubo_ranges[i]; + prog_data->ubo_ranges[prog_data->num_ubo_ranges++] = *range; + prog_data->ubo_size += range->size; + } + + if (prog_data->ubo_size) { + if (V3D_DEBUG & V3D_DEBUG_SHADERDB) { + fprintf(stderr, "SHADER-DB: %s prog %d/%d: %d UBO uniforms\n", + vir_get_stage_name(c), + c->program_id, c->variant_id, + prog_data->ubo_size / 4); + } + } +} + +static void +v3d_set_prog_data(struct v3d_compile *c, + struct v3d_prog_data *prog_data) +{ + v3d_set_prog_data_uniforms(c, prog_data); + v3d_set_prog_data_ubo(c, prog_data); +} + +static uint64_t * +v3d_return_qpu_insts(struct v3d_compile *c, uint32_t *final_assembly_size) +{ + *final_assembly_size = c->qpu_inst_count * sizeof(uint64_t); + + uint64_t *qpu_insts = malloc(*final_assembly_size); + if (!qpu_insts) + return NULL; + + memcpy(qpu_insts, c->qpu_insts, *final_assembly_size); + + vir_compile_destroy(c); + + return qpu_insts; +} + +uint64_t *v3d_compile_vs(const struct v3d_compiler *compiler, + struct v3d_vs_key *key, + struct v3d_vs_prog_data *prog_data, + nir_shader *s, + int program_id, int variant_id, + uint32_t *final_assembly_size) +{ + struct v3d_compile *c = vir_compile_init(compiler, &key->base, s, + program_id, variant_id); + + c->vs_key = key; + + v3d_lower_nir(c); + + if (key->clamp_color) + NIR_PASS_V(c->s, nir_lower_clamp_color_outputs); + + if (key->base.ucp_enables) { + NIR_PASS_V(c->s, nir_lower_clip_vs, key->base.ucp_enables); + NIR_PASS_V(c->s, nir_lower_io_to_scalar, + nir_var_shader_out); + } + + /* Note: VS output scalarizing must happen after nir_lower_clip_vs. */ + NIR_PASS_V(c->s, nir_lower_io_to_scalar, nir_var_shader_out); + + v3d_lower_nir_late(c); + v3d_optimize_nir(c->s); + NIR_PASS_V(c->s, nir_convert_from_ssa, true); + + v3d_nir_to_vir(c); + + v3d_set_prog_data(c, &prog_data->base); + + prog_data->base.num_inputs = c->num_inputs; + + /* The vertex data gets format converted by the VPM so that + * each attribute channel takes up a VPM column. Precompute + * the sizes for the shader record. + */ + for (int i = 0; i < ARRAY_SIZE(prog_data->vattr_sizes); i++) { + prog_data->vattr_sizes[i] = c->vattr_sizes[i]; + prog_data->vpm_input_size += c->vattr_sizes[i]; + } + + /* Input/output segment size are in 8x32-bit multiples. */ + prog_data->vpm_input_size = align(prog_data->vpm_input_size, 8) / 8; + prog_data->vpm_output_size = align(c->num_vpm_writes, 8) / 8; + + prog_data->uses_vid = (s->info.system_values_read & + (1ull << SYSTEM_VALUE_VERTEX_ID)); + prog_data->uses_iid = (s->info.system_values_read & + (1ull << SYSTEM_VALUE_INSTANCE_ID)); + + return v3d_return_qpu_insts(c, final_assembly_size); +} + +static void +v3d_set_fs_prog_data_inputs(struct v3d_compile *c, + struct v3d_fs_prog_data *prog_data) +{ + prog_data->base.num_inputs = c->num_inputs; + memcpy(prog_data->input_slots, c->input_slots, + c->num_inputs * sizeof(*c->input_slots)); + + memcpy(prog_data->flat_shade_flags, c->flat_shade_flags, + sizeof(c->flat_shade_flags)); + memcpy(prog_data->shade_model_flags, c->shade_model_flags, + sizeof(c->shade_model_flags)); +} + +uint64_t *v3d_compile_fs(const struct v3d_compiler *compiler, + struct v3d_fs_key *key, + struct v3d_fs_prog_data *prog_data, + nir_shader *s, + int program_id, int variant_id, + uint32_t *final_assembly_size) +{ + struct v3d_compile *c = vir_compile_init(compiler, &key->base, s, + program_id, variant_id); + + c->fs_key = key; + + v3d_lower_nir(c); + + if (key->light_twoside) + NIR_PASS_V(c->s, nir_lower_two_sided_color); + + if (key->clamp_color) + NIR_PASS_V(c->s, nir_lower_clamp_color_outputs); + + if (key->alpha_test) { + NIR_PASS_V(c->s, nir_lower_alpha_test, key->alpha_test_func, + false); + } + + if (key->base.ucp_enables) + NIR_PASS_V(c->s, nir_lower_clip_fs, key->base.ucp_enables); + + /* Note: FS input scalarizing must happen after + * nir_lower_two_sided_color, which only handles a vec4 at a time. + */ + NIR_PASS_V(c->s, nir_lower_io_to_scalar, nir_var_shader_in); + + v3d_lower_nir_late(c); + v3d_optimize_nir(c->s); + NIR_PASS_V(c->s, nir_convert_from_ssa, true); + + v3d_nir_to_vir(c); + + v3d_set_prog_data(c, &prog_data->base); + v3d_set_fs_prog_data_inputs(c, prog_data); + prog_data->writes_z = (c->s->info.outputs_written & + (1 << FRAG_RESULT_DEPTH)); + prog_data->discard = c->s->info.fs.uses_discard; + + return v3d_return_qpu_insts(c, final_assembly_size); +} + +void +vir_remove_instruction(struct v3d_compile *c, struct qinst *qinst) +{ + if (qinst->dst.file == QFILE_TEMP) + c->defs[qinst->dst.index] = NULL; + + list_del(&qinst->link); + free(qinst); +} + +struct qreg +vir_follow_movs(struct v3d_compile *c, struct qreg reg) +{ + /* XXX + int pack = reg.pack; + + while (reg.file == QFILE_TEMP && + c->defs[reg.index] && + (c->defs[reg.index]->op == QOP_MOV || + c->defs[reg.index]->op == QOP_FMOV) && + !c->defs[reg.index]->dst.pack && + !c->defs[reg.index]->src[0].pack) { + reg = c->defs[reg.index]->src[0]; + } + + reg.pack = pack; + */ + return reg; +} + +void +vir_compile_destroy(struct v3d_compile *c) +{ + vir_for_each_block(block, c) { + while (!list_empty(&block->instructions)) { + struct qinst *qinst = + list_first_entry(&block->instructions, + struct qinst, link); + vir_remove_instruction(c, qinst); + } + } + + ralloc_free(c); +} + +struct qreg +vir_uniform(struct v3d_compile *c, + enum quniform_contents contents, + uint32_t data) +{ + for (int i = 0; i < c->num_uniforms; i++) { + if (c->uniform_contents[i] == contents && + c->uniform_data[i] == data) { + return vir_reg(QFILE_UNIF, i); + } + } + + uint32_t uniform = c->num_uniforms++; + + if (uniform >= c->uniform_array_size) { + c->uniform_array_size = MAX2(MAX2(16, uniform + 1), + c->uniform_array_size * 2); + + c->uniform_data = reralloc(c, c->uniform_data, + uint32_t, + c->uniform_array_size); + c->uniform_contents = reralloc(c, c->uniform_contents, + enum quniform_contents, + c->uniform_array_size); + } + + c->uniform_contents[uniform] = contents; + c->uniform_data[uniform] = data; + + return vir_reg(QFILE_UNIF, uniform); +} + +void +vir_PF(struct v3d_compile *c, struct qreg src, enum v3d_qpu_pf pf) +{ + struct qinst *last_inst = NULL; + + if (!list_empty(&c->cur_block->instructions)) + last_inst = (struct qinst *)c->cur_block->instructions.prev; + + if (src.file != QFILE_TEMP || + !c->defs[src.index] || + last_inst != c->defs[src.index]) { + /* XXX: Make the MOV be the appropriate type */ + last_inst = vir_MOV_dest(c, vir_reg(QFILE_NULL, 0), src); + last_inst = (struct qinst *)c->cur_block->instructions.prev; + } + + vir_set_pf(last_inst, pf); +} + +#define OPTPASS(func) \ + do { \ + bool stage_progress = func(c); \ + if (stage_progress) { \ + progress = true; \ + if (print_opt_debug) { \ + fprintf(stderr, \ + "VIR opt pass %2d: %s progress\n", \ + pass, #func); \ + } \ + /*XXX vir_validate(c);*/ \ + } \ + } while (0) + +void +vir_optimize(struct v3d_compile *c) +{ + bool print_opt_debug = false; + int pass = 1; + + while (true) { + bool progress = false; + + OPTPASS(vir_opt_copy_propagate); + OPTPASS(vir_opt_dead_code); + + if (!progress) + break; + + pass++; + } +} + +const char * +vir_get_stage_name(struct v3d_compile *c) +{ + if (c->vs_key && c->vs_key->is_coord) + return "MESA_SHADER_COORD"; + else + return gl_shader_stage_name(c->s->info.stage); +} diff --git a/lib/mesa/src/broadcom/compiler/vir_dump.c b/lib/mesa/src/broadcom/compiler/vir_dump.c new file mode 100644 index 000000000..ad5c061a1 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/vir_dump.c @@ -0,0 +1,339 @@ +/* + * Copyright © 2016-2017 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "v3d_compiler.h" + +static void +vir_print_reg(struct v3d_compile *c, struct qreg reg) +{ + static const char *files[] = { + [QFILE_TEMP] = "t", + [QFILE_VARY] = "v", + [QFILE_UNIF] = "u", + [QFILE_TLB] = "tlb", + [QFILE_TLBU] = "tlbu", + }; + static const char *quniform_names[] = { + [QUNIFORM_VIEWPORT_X_SCALE] = "vp_x_scale", + [QUNIFORM_VIEWPORT_Y_SCALE] = "vp_y_scale", + [QUNIFORM_VIEWPORT_Z_OFFSET] = "vp_z_offset", + [QUNIFORM_VIEWPORT_Z_SCALE] = "vp_z_scale", + }; + + switch (reg.file) { + + case QFILE_NULL: + fprintf(stderr, "null"); + break; + + case QFILE_LOAD_IMM: + fprintf(stderr, "0x%08x (%f)", reg.index, uif(reg.index)); + break; + + case QFILE_REG: + fprintf(stderr, "rf%d", reg.index); + break; + + case QFILE_MAGIC: + fprintf(stderr, "%s", v3d_qpu_magic_waddr_name(reg.index)); + break; + + case QFILE_SMALL_IMM: + if ((int)reg.index >= -16 && (int)reg.index <= 15) + fprintf(stderr, "%d", reg.index); + else + fprintf(stderr, "%f", uif(reg.index)); + break; + + case QFILE_VPM: + fprintf(stderr, "vpm%d.%d", + reg.index / 4, reg.index % 4); + break; + + case QFILE_TLB: + fprintf(stderr, "%s", files[reg.file]); + break; + + case QFILE_UNIF: { + enum quniform_contents contents = c->uniform_contents[reg.index]; + + fprintf(stderr, "%s%d", files[reg.file], reg.index); + + switch (contents) { + case QUNIFORM_CONSTANT: + fprintf(stderr, " (0x%08x / %f)", + c->uniform_data[reg.index], + uif(c->uniform_data[reg.index])); + break; + + case QUNIFORM_UNIFORM: + fprintf(stderr, " (push[%d])", + c->uniform_data[reg.index]); + break; + + case QUNIFORM_TEXTURE_CONFIG_P1: + fprintf(stderr, " (tex[%d].p1)", + c->uniform_data[reg.index]); + break; + + case QUNIFORM_TEXTURE_WIDTH: + fprintf(stderr, " (tex[%d].width)", + c->uniform_data[reg.index]); + break; + case QUNIFORM_TEXTURE_HEIGHT: + fprintf(stderr, " (tex[%d].height)", + c->uniform_data[reg.index]); + break; + case QUNIFORM_TEXTURE_DEPTH: + fprintf(stderr, " (tex[%d].depth)", + c->uniform_data[reg.index]); + break; + case QUNIFORM_TEXTURE_ARRAY_SIZE: + fprintf(stderr, " (tex[%d].array_size)", + c->uniform_data[reg.index]); + break; + case QUNIFORM_TEXTURE_LEVELS: + fprintf(stderr, " (tex[%d].levels)", + c->uniform_data[reg.index]); + break; + + case QUNIFORM_UBO_ADDR: + fprintf(stderr, " (ubo[%d])", + c->uniform_data[reg.index]); + break; + + default: + if (quniform_contents_is_texture_p0(contents)) { + fprintf(stderr, " (tex[%d].p0: 0x%08x)", + contents - QUNIFORM_TEXTURE_CONFIG_P0_0, + c->uniform_data[reg.index]); + } else if (contents < ARRAY_SIZE(quniform_names)) { + fprintf(stderr, " (%s)", + quniform_names[contents]); + } else { + fprintf(stderr, " (%d / 0x%08x)", contents, + c->uniform_data[reg.index]); + } + } + + break; + } + + default: + fprintf(stderr, "%s%d", files[reg.file], reg.index); + break; + } +} + +static void +vir_dump_sig(struct v3d_compile *c, struct qinst *inst) +{ + struct v3d_qpu_sig *sig = &inst->qpu.sig; + + if (sig->thrsw) + fprintf(stderr, "; thrsw"); + if (sig->ldvary) + fprintf(stderr, "; ldvary"); + if (sig->ldvpm) + fprintf(stderr, "; ldvpm"); + if (sig->ldtmu) + fprintf(stderr, "; ldtmu"); + if (sig->ldunif) + fprintf(stderr, "; ldunif"); + if (sig->wrtmuc) + fprintf(stderr, "; wrtmuc"); +} + +static void +vir_dump_alu(struct v3d_compile *c, struct qinst *inst) +{ + struct v3d_qpu_instr *instr = &inst->qpu; + int nsrc = vir_get_non_sideband_nsrc(inst); + int sideband_nsrc = vir_get_nsrc(inst); + enum v3d_qpu_input_unpack unpack[2]; + + if (inst->qpu.alu.add.op != V3D_QPU_A_NOP) { + fprintf(stderr, "%s", v3d_qpu_add_op_name(instr->alu.add.op)); + fprintf(stderr, "%s", v3d_qpu_cond_name(instr->flags.ac)); + fprintf(stderr, "%s", v3d_qpu_pf_name(instr->flags.apf)); + fprintf(stderr, "%s", v3d_qpu_uf_name(instr->flags.auf)); + fprintf(stderr, " "); + + vir_print_reg(c, inst->dst); + fprintf(stderr, "%s", v3d_qpu_pack_name(instr->alu.add.output_pack)); + + unpack[0] = instr->alu.add.a_unpack; + unpack[1] = instr->alu.add.b_unpack; + } else { + fprintf(stderr, "%s", v3d_qpu_mul_op_name(instr->alu.mul.op)); + fprintf(stderr, "%s", v3d_qpu_cond_name(instr->flags.mc)); + fprintf(stderr, "%s", v3d_qpu_pf_name(instr->flags.mpf)); + fprintf(stderr, "%s", v3d_qpu_uf_name(instr->flags.muf)); + fprintf(stderr, " "); + + vir_print_reg(c, inst->dst); + fprintf(stderr, "%s", v3d_qpu_pack_name(instr->alu.mul.output_pack)); + + unpack[0] = instr->alu.mul.a_unpack; + unpack[1] = instr->alu.mul.b_unpack; + } + + for (int i = 0; i < sideband_nsrc; i++) { + fprintf(stderr, ", "); + vir_print_reg(c, inst->src[i]); + if (i < nsrc) + fprintf(stderr, "%s", v3d_qpu_unpack_name(unpack[i])); + } + + vir_dump_sig(c, inst); +} + +void +vir_dump_inst(struct v3d_compile *c, struct qinst *inst) +{ + struct v3d_qpu_instr *instr = &inst->qpu; + + switch (inst->qpu.type) { + case V3D_QPU_INSTR_TYPE_ALU: + vir_dump_alu(c, inst); + break; + case V3D_QPU_INSTR_TYPE_BRANCH: + fprintf(stderr, "b"); + if (instr->branch.ub) + fprintf(stderr, "u"); + + fprintf(stderr, "%s", + v3d_qpu_branch_cond_name(instr->branch.cond)); + fprintf(stderr, "%s", v3d_qpu_msfign_name(instr->branch.msfign)); + + switch (instr->branch.bdi) { + case V3D_QPU_BRANCH_DEST_ABS: + fprintf(stderr, " zero_addr+0x%08x", instr->branch.offset); + break; + + case V3D_QPU_BRANCH_DEST_REL: + fprintf(stderr, " %d", instr->branch.offset); + break; + + case V3D_QPU_BRANCH_DEST_LINK_REG: + fprintf(stderr, " lri"); + break; + + case V3D_QPU_BRANCH_DEST_REGFILE: + fprintf(stderr, " rf%d", instr->branch.raddr_a); + break; + } + + if (instr->branch.ub) { + switch (instr->branch.bdu) { + case V3D_QPU_BRANCH_DEST_ABS: + fprintf(stderr, ", a:unif"); + break; + + case V3D_QPU_BRANCH_DEST_REL: + fprintf(stderr, ", r:unif"); + break; + + case V3D_QPU_BRANCH_DEST_LINK_REG: + fprintf(stderr, ", lri"); + break; + + case V3D_QPU_BRANCH_DEST_REGFILE: + fprintf(stderr, ", rf%d", instr->branch.raddr_a); + break; + } + } + + if (vir_has_implicit_uniform(inst)) { + fprintf(stderr, " "); + vir_print_reg(c, inst->src[vir_get_implicit_uniform_src(inst)]); + } + + break; + } +} + +void +vir_dump(struct v3d_compile *c) +{ + int ip = 0; + + vir_for_each_block(block, c) { + fprintf(stderr, "BLOCK %d:\n", block->index); + vir_for_each_inst(inst, block) { + if (c->temp_start) { + bool first = true; + + for (int i = 0; i < c->num_temps; i++) { + if (c->temp_start[i] != ip) + continue; + + if (first) { + first = false; + } else { + fprintf(stderr, ", "); + } + fprintf(stderr, "S%4d", i); + } + + if (first) + fprintf(stderr, " "); + else + fprintf(stderr, " "); + } + + if (c->temp_end) { + bool first = true; + + for (int i = 0; i < c->num_temps; i++) { + if (c->temp_end[i] != ip) + continue; + + if (first) { + first = false; + } else { + fprintf(stderr, ", "); + } + fprintf(stderr, "E%4d", i); + } + + if (first) + fprintf(stderr, " "); + else + fprintf(stderr, " "); + } + + vir_dump_inst(c, inst); + fprintf(stderr, "\n"); + ip++; + } + if (block->successors[1]) { + fprintf(stderr, "-> BLOCK %d, %d\n", + block->successors[0]->index, + block->successors[1]->index); + } else if (block->successors[0]) { + fprintf(stderr, "-> BLOCK %d\n", + block->successors[0]->index); + } + } +} diff --git a/lib/mesa/src/broadcom/compiler/vir_live_variables.c b/lib/mesa/src/broadcom/compiler/vir_live_variables.c new file mode 100644 index 000000000..217b716fd --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/vir_live_variables.c @@ -0,0 +1,340 @@ +/* + * Copyright © 2012 Intel Corporation + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +#define MAX_INSTRUCTION (1 << 30) + +#include "util/ralloc.h" +#include "util/register_allocate.h" +#include "v3d_compiler.h" + +struct partial_update_state { + struct qinst *insts[4]; + uint8_t channels; +}; + +static uint32_t +int_hash(const void *key) +{ + return _mesa_hash_data(key, sizeof(int)); +} + +static bool +int_compare(const void *key1, const void *key2) +{ + return *(const int *)key1 == *(const int *)key2; +} + +static int +vir_reg_to_var(struct qreg reg) +{ + if (reg.file == QFILE_TEMP) + return reg.index; + + return -1; +} + +static void +vir_setup_use(struct v3d_compile *c, struct qblock *block, int ip, + struct qreg src) +{ + int var = vir_reg_to_var(src); + if (var == -1) + return; + + c->temp_start[var] = MIN2(c->temp_start[var], ip); + c->temp_end[var] = MAX2(c->temp_end[var], ip); + + /* The use[] bitset marks when the block makes + * use of a variable without having completely + * defined that variable within the block. + */ + if (!BITSET_TEST(block->def, var)) + BITSET_SET(block->use, var); +} + +static struct partial_update_state * +get_partial_update_state(struct hash_table *partial_update_ht, + struct qinst *inst) +{ + struct hash_entry *entry = + _mesa_hash_table_search(partial_update_ht, + &inst->dst.index); + if (entry) + return entry->data; + + struct partial_update_state *state = + rzalloc(partial_update_ht, struct partial_update_state); + + _mesa_hash_table_insert(partial_update_ht, &inst->dst.index, state); + + return state; +} + +static void +vir_setup_def(struct v3d_compile *c, struct qblock *block, int ip, + struct hash_table *partial_update_ht, struct qinst *inst) +{ + if (inst->qpu.type != V3D_QPU_INSTR_TYPE_ALU) + return; + + /* The def[] bitset marks when an initialization in a + * block completely screens off previous updates of + * that variable. + */ + int var = vir_reg_to_var(inst->dst); + if (var == -1) + return; + + c->temp_start[var] = MIN2(c->temp_start[var], ip); + c->temp_end[var] = MAX2(c->temp_end[var], ip); + + /* If we've already tracked this as a def, or already used it within + * the block, there's nothing to do. + */ + if (BITSET_TEST(block->use, var) || BITSET_TEST(block->def, var)) + return; + + /* Easy, common case: unconditional full register update. + * + * We treat conditioning on the exec mask as the same as not being + * conditional. This makes sure that if the register gets set on + * either side of an if, it is treated as being screened off before + * the if. Otherwise, if there was no intervening def, its live + * interval doesn't extend back to the start of he program, and if too + * many registers did that we'd fail to register allocate. + */ + if (((inst->qpu.flags.ac == V3D_QPU_COND_NONE && + inst->qpu.flags.mc == V3D_QPU_COND_NONE) || + inst->cond_is_exec_mask) && + inst->qpu.alu.add.output_pack == V3D_QPU_PACK_NONE && + inst->qpu.alu.mul.output_pack == V3D_QPU_PACK_NONE) { + BITSET_SET(block->def, var); + return; + } + + /* Finally, look at the condition code and packing and mark it as a + * def. We need to make sure that we understand sequences + * instructions like: + * + * mov.zs t0, t1 + * mov.zc t0, t2 + * + * or: + * + * mmov t0.8a, t1 + * mmov t0.8b, t2 + * mmov t0.8c, t3 + * mmov t0.8d, t4 + * + * as defining the temp within the block, because otherwise dst's live + * range will get extended up the control flow to the top of the + * program. + */ + struct partial_update_state *state = + get_partial_update_state(partial_update_ht, inst); + uint8_t mask = 0xf; /* XXX vir_channels_written(inst); */ + + if (inst->qpu.flags.ac == V3D_QPU_COND_NONE && + inst->qpu.flags.mc == V3D_QPU_COND_NONE) { + state->channels |= mask; + } else { + for (int i = 0; i < 4; i++) { + if (!(mask & (1 << i))) + continue; + + /* XXXif (state->insts[i] && + state->insts[i]->cond == + qpu_cond_complement(inst->cond)) + state->channels |= 1 << i; + else + */ + state->insts[i] = inst; + } + } + + if (state->channels == 0xf) + BITSET_SET(block->def, var); +} + +static void +sf_state_clear(struct hash_table *partial_update_ht) +{ + struct hash_entry *entry; + + hash_table_foreach(partial_update_ht, entry) { + struct partial_update_state *state = entry->data; + + for (int i = 0; i < 4; i++) { + if (state->insts[i] && + (state->insts[i]->qpu.flags.ac != V3D_QPU_COND_NONE || + state->insts[i]->qpu.flags.mc != V3D_QPU_COND_NONE)) + state->insts[i] = NULL; + } + } +} + +/* Sets up the def/use arrays for when variables are used-before-defined or + * defined-before-used in the block. + * + * Also initializes the temp_start/temp_end to cover just the instruction IPs + * where the variable is used, which will be extended later in + * vir_compute_start_end(). + */ +static void +vir_setup_def_use(struct v3d_compile *c) +{ + struct hash_table *partial_update_ht = + _mesa_hash_table_create(c, int_hash, int_compare); + int ip = 0; + + vir_for_each_block(block, c) { + block->start_ip = ip; + + _mesa_hash_table_clear(partial_update_ht, NULL); + + vir_for_each_inst(inst, block) { + for (int i = 0; i < vir_get_nsrc(inst); i++) + vir_setup_use(c, block, ip, inst->src[i]); + + vir_setup_def(c, block, ip, partial_update_ht, inst); + + if (false /* XXX inst->uf */) + sf_state_clear(partial_update_ht); + + /* Payload registers: r0/1/2 contain W, centroid W, + * and Z at program start. Register allocation will + * force their nodes to R0/1/2. + */ + if (inst->src[0].file == QFILE_REG) { + switch (inst->src[0].index) { + case 0: + case 1: + case 2: + c->temp_start[inst->dst.index] = 0; + break; + } + } + + ip++; + } + block->end_ip = ip; + } + + _mesa_hash_table_destroy(partial_update_ht, NULL); +} + +static bool +vir_live_variables_dataflow(struct v3d_compile *c, int bitset_words) +{ + bool cont = false; + + vir_for_each_block_rev(block, c) { + /* Update live_out: Any successor using the variable + * on entrance needs us to have the variable live on + * exit. + */ + vir_for_each_successor(succ, block) { + for (int i = 0; i < bitset_words; i++) { + BITSET_WORD new_live_out = (succ->live_in[i] & + ~block->live_out[i]); + if (new_live_out) { + block->live_out[i] |= new_live_out; + cont = true; + } + } + } + + /* Update live_in */ + for (int i = 0; i < bitset_words; i++) { + BITSET_WORD new_live_in = (block->use[i] | + (block->live_out[i] & + ~block->def[i])); + if (new_live_in & ~block->live_in[i]) { + block->live_in[i] |= new_live_in; + cont = true; + } + } + } + + return cont; +} + +/** + * Extend the start/end ranges for each variable to account for the + * new information calculated from control flow. + */ +static void +vir_compute_start_end(struct v3d_compile *c, int num_vars) +{ + vir_for_each_block(block, c) { + for (int i = 0; i < num_vars; i++) { + if (BITSET_TEST(block->live_in, i)) { + c->temp_start[i] = MIN2(c->temp_start[i], + block->start_ip); + c->temp_end[i] = MAX2(c->temp_end[i], + block->start_ip); + } + + if (BITSET_TEST(block->live_out, i)) { + c->temp_start[i] = MIN2(c->temp_start[i], + block->end_ip); + c->temp_end[i] = MAX2(c->temp_end[i], + block->end_ip); + } + } + } +} + +void +vir_calculate_live_intervals(struct v3d_compile *c) +{ + int bitset_words = BITSET_WORDS(c->num_temps); + + /* If we called this function more than once, then we should be + * freeing the previous arrays. + */ + assert(!c->temp_start); + + c->temp_start = rzalloc_array(c, int, c->num_temps); + c->temp_end = rzalloc_array(c, int, c->num_temps); + + for (int i = 0; i < c->num_temps; i++) { + c->temp_start[i] = MAX_INSTRUCTION; + c->temp_end[i] = -1; + } + + vir_for_each_block(block, c) { + block->def = rzalloc_array(c, BITSET_WORD, bitset_words); + block->use = rzalloc_array(c, BITSET_WORD, bitset_words); + block->live_in = rzalloc_array(c, BITSET_WORD, bitset_words); + block->live_out = rzalloc_array(c, BITSET_WORD, bitset_words); + } + + vir_setup_def_use(c); + + while (vir_live_variables_dataflow(c, bitset_words)) + ; + + vir_compute_start_end(c, c->num_temps); +} diff --git a/lib/mesa/src/broadcom/compiler/vir_lower_uniforms.c b/lib/mesa/src/broadcom/compiler/vir_lower_uniforms.c new file mode 100644 index 000000000..7f3bb8460 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/vir_lower_uniforms.c @@ -0,0 +1,209 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/** + * @file v3d_vir_lower_uniforms.c + * + * This is the pre-code-generation pass for fixing up instructions that try to + * read from multiple uniform values. + */ + +#include "v3d_compiler.h" +#include "util/hash_table.h" +#include "util/u_math.h" + +static inline uint32_t +index_hash(const void *key) +{ + return (uintptr_t)key; +} + +static inline bool +index_compare(const void *a, const void *b) +{ + return a == b; +} + +static void +add_uniform(struct hash_table *ht, struct qreg reg) +{ + struct hash_entry *entry; + void *key = (void *)(uintptr_t)(reg.index + 1); + + entry = _mesa_hash_table_search(ht, key); + if (entry) { + entry->data++; + } else { + _mesa_hash_table_insert(ht, key, (void *)(uintptr_t)1); + } +} + +static void +remove_uniform(struct hash_table *ht, struct qreg reg) +{ + struct hash_entry *entry; + void *key = (void *)(uintptr_t)(reg.index + 1); + + entry = _mesa_hash_table_search(ht, key); + assert(entry); + entry->data = (void *)(((uintptr_t) entry->data) - 1); + if (entry->data == NULL) + _mesa_hash_table_remove(ht, entry); +} + +static bool +is_lowerable_uniform(struct qinst *inst, int i) +{ + if (inst->src[i].file != QFILE_UNIF) + return false; + if (vir_has_implicit_uniform(inst)) + return i != vir_get_implicit_uniform_src(inst); + return true; +} + +/* Returns the number of different uniform values referenced by the + * instruction. + */ +static uint32_t +vir_get_instruction_uniform_count(struct qinst *inst) +{ + uint32_t count = 0; + + for (int i = 0; i < vir_get_nsrc(inst); i++) { + if (inst->src[i].file != QFILE_UNIF) + continue; + + bool is_duplicate = false; + for (int j = 0; j < i; j++) { + if (inst->src[j].file == QFILE_UNIF && + inst->src[j].index == inst->src[i].index) { + is_duplicate = true; + break; + } + } + if (!is_duplicate) + count++; + } + + return count; +} + +void +vir_lower_uniforms(struct v3d_compile *c) +{ + struct hash_table *ht = + _mesa_hash_table_create(c, index_hash, index_compare); + + /* Walk the instruction list, finding which instructions have more + * than one uniform referenced, and add those uniform values to the + * ht. + */ + vir_for_each_inst_inorder(inst, c) { + uint32_t nsrc = vir_get_nsrc(inst); + + if (vir_get_instruction_uniform_count(inst) <= 1) + continue; + + for (int i = 0; i < nsrc; i++) { + if (is_lowerable_uniform(inst, i)) + add_uniform(ht, inst->src[i]); + } + } + + while (ht->entries) { + /* Find the most commonly used uniform in instructions that + * need a uniform lowered. + */ + uint32_t max_count = 0; + uint32_t max_index = 0; + struct hash_entry *entry; + hash_table_foreach(ht, entry) { + uint32_t count = (uintptr_t)entry->data; + uint32_t index = (uintptr_t)entry->key - 1; + if (count > max_count) { + max_count = count; + max_index = index; + } + } + + struct qreg unif = vir_reg(QFILE_UNIF, max_index); + + /* Now, find the instructions using this uniform and make them + * reference a temp instead. + */ + vir_for_each_block(block, c) { + struct qinst *mov = NULL; + + vir_for_each_inst(inst, block) { + uint32_t nsrc = vir_get_nsrc(inst); + + uint32_t count = vir_get_instruction_uniform_count(inst); + + if (count <= 1) + continue; + + /* If the block doesn't have a load of the + * uniform yet, add it. We could potentially + * do better and CSE MOVs from multiple blocks + * into dominating blocks, except that may + * cause troubles for register allocation. + */ + if (!mov) { + mov = vir_mul_inst(V3D_QPU_M_MOV, + vir_get_temp(c), + unif, c->undef); + list_add(&mov->link, + &block->instructions); + c->defs[mov->dst.index] = mov; + } + + bool removed = false; + for (int i = 0; i < nsrc; i++) { + if (is_lowerable_uniform(inst, i) && + inst->src[i].index == max_index) { + inst->src[i].file = + mov->dst.file; + inst->src[i].index = + mov->dst.index; + remove_uniform(ht, unif); + removed = true; + } + } + if (removed) + count--; + + /* If the instruction doesn't need lowering any more, + * then drop it from the list. + */ + if (count <= 1) { + for (int i = 0; i < nsrc; i++) { + if (is_lowerable_uniform(inst, i)) + remove_uniform(ht, inst->src[i]); + } + } + } + } + } + + _mesa_hash_table_destroy(ht, NULL); +} diff --git a/lib/mesa/src/broadcom/compiler/vir_opt_copy_propagate.c b/lib/mesa/src/broadcom/compiler/vir_opt_copy_propagate.c new file mode 100644 index 000000000..2a22a1b55 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/vir_opt_copy_propagate.c @@ -0,0 +1,233 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/** + * @file v3d_opt_copy_propagation.c + * + * This implements simple copy propagation for VIR without control flow. + * + * For each temp, it keeps a qreg of which source it was MOVed from, if it + * was. If we see that used later, we can just reuse the source value, since + * we know we don't have control flow, and we have SSA for our values so + * there's no killing to worry about. + */ + +#include "v3d_compiler.h" + +static bool +is_copy_mov(struct qinst *inst) +{ + if (!inst) + return false; + + if (inst->qpu.type != V3D_QPU_INSTR_TYPE_ALU || + (inst->qpu.alu.mul.op != V3D_QPU_M_FMOV && + inst->qpu.alu.mul.op != V3D_QPU_M_MOV)) { + return false; + } + + if (inst->dst.file != QFILE_TEMP) + return false; + + if (inst->src[0].file != QFILE_TEMP && + inst->src[0].file != QFILE_UNIF) { + return false; + } + + if (inst->qpu.alu.add.output_pack != V3D_QPU_PACK_NONE || + inst->qpu.alu.mul.output_pack != V3D_QPU_PACK_NONE) { + return false; + } + + if (inst->qpu.flags.ac != V3D_QPU_COND_NONE || + inst->qpu.flags.mc != V3D_QPU_COND_NONE) { + return false; + } + + switch (inst->src[0].file) { + case QFILE_MAGIC: + /* No copy propagating from R3/R4/R5 -- the MOVs from those + * are there to register allocate values produced into R3/4/5 + * to other regs (though hopefully r3/4/5). + */ + switch (inst->src[0].index) { + case V3D_QPU_WADDR_R3: + case V3D_QPU_WADDR_R4: + case V3D_QPU_WADDR_R5: + return false; + default: + break; + } + break; + + case QFILE_REG: + switch (inst->src[0].index) { + case 0: + case 1: + case 2: + /* MOVs from rf0/1/2 are only to track the live + * intervals for W/centroid W/Z. + */ + return false; + } + break; + + default: + break; + } + + return true; +} + +static bool +vir_has_unpack(struct qinst *inst, int chan) +{ + assert(chan == 0 || chan == 1); + + if (vir_is_add(inst)) { + if (chan == 0) + return inst->qpu.alu.add.a_unpack != V3D_QPU_UNPACK_NONE; + else + return inst->qpu.alu.add.b_unpack != V3D_QPU_UNPACK_NONE; + } else { + if (chan == 0) + return inst->qpu.alu.mul.a_unpack != V3D_QPU_UNPACK_NONE; + else + return inst->qpu.alu.mul.b_unpack != V3D_QPU_UNPACK_NONE; + } +} + +static bool +try_copy_prop(struct v3d_compile *c, struct qinst *inst, struct qinst **movs) +{ + bool debug = false; + bool progress = false; + + for (int i = 0; i < vir_get_nsrc(inst); i++) { + if (inst->src[i].file != QFILE_TEMP) + continue; + + /* We have two ways of finding MOVs we can copy propagate + * from. One is if it's an SSA def: then we can reuse it from + * any block in the program, as long as its source is also an + * SSA def. Alternatively, if it's in the "movs" array + * tracked within the block, then we know the sources for it + * haven't been changed since we saw the instruction within + * our block. + */ + struct qinst *mov = movs[inst->src[i].index]; + if (!mov) { + if (!is_copy_mov(c->defs[inst->src[i].index])) + continue; + mov = c->defs[inst->src[i].index]; + + if (mov->src[0].file == QFILE_TEMP && + !c->defs[mov->src[0].index]) + continue; + } + + if (vir_has_unpack(mov, 0)) { + /* Make sure that the meaning of the unpack + * would be the same between the two + * instructions. + */ + if (vir_is_float_input(inst) != + vir_is_float_input(mov)) { + continue; + } + /* No composing the unpacks. */ + if (vir_has_unpack(inst, i)) + continue; + } + + if (debug) { + fprintf(stderr, "Copy propagate: "); + vir_dump_inst(c, inst); + fprintf(stderr, "\n"); + } + + inst->src[i] = mov->src[0]; + if (vir_has_unpack(mov, 0)) { + enum v3d_qpu_input_unpack unpack = mov->qpu.alu.mul.a_unpack; + + vir_set_unpack(inst, i, unpack); + } + + if (debug) { + fprintf(stderr, "to: "); + vir_dump_inst(c, inst); + fprintf(stderr, "\n"); + } + + progress = true; + } + + return progress; +} + +static void +apply_kills(struct v3d_compile *c, struct qinst **movs, struct qinst *inst) +{ + if (inst->dst.file != QFILE_TEMP) + return; + + for (int i = 0; i < c->num_temps; i++) { + if (movs[i] && + (movs[i]->dst.index == inst->dst.index || + (movs[i]->src[0].file == QFILE_TEMP && + movs[i]->src[0].index == inst->dst.index))) { + movs[i] = NULL; + } + } +} + +bool +vir_opt_copy_propagate(struct v3d_compile *c) +{ + bool progress = false; + struct qinst **movs; + + movs = ralloc_array(c, struct qinst *, c->num_temps); + if (!movs) + return false; + + vir_for_each_block(block, c) { + /* The MOVs array tracks only available movs within the + * block. + */ + memset(movs, 0, sizeof(struct qinst *) * c->num_temps); + + vir_for_each_inst(inst, block) { + progress = try_copy_prop(c, inst, movs) || progress; + + apply_kills(c, movs, inst); + + if (is_copy_mov(inst)) + movs[inst->dst.index] = inst; + } + } + + ralloc_free(movs); + + return progress; +} diff --git a/lib/mesa/src/broadcom/compiler/vir_opt_dead_code.c b/lib/mesa/src/broadcom/compiler/vir_opt_dead_code.c new file mode 100644 index 000000000..9e0ef20b6 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/vir_opt_dead_code.c @@ -0,0 +1,162 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/** + * @file v3d_opt_dead_code.c + * + * This is a simple dead code eliminator for SSA values in VIR. + * + * It walks all the instructions finding what temps are used, then walks again + * to remove instructions writing unused temps. + * + * This is an inefficient implementation if you have long chains of + * instructions where the entire chain is dead, but we expect those to have + * been eliminated at the NIR level, and here we're just cleaning up small + * problems produced by NIR->VIR. + */ + +#include "v3d_compiler.h" + +static bool debug; + +static void +dce(struct v3d_compile *c, struct qinst *inst) +{ + if (debug) { + fprintf(stderr, "Removing: "); + vir_dump_inst(c, inst); + fprintf(stderr, "\n"); + } + assert(inst->qpu.flags.apf == V3D_QPU_PF_NONE); + assert(inst->qpu.flags.mpf == V3D_QPU_PF_NONE); + vir_remove_instruction(c, inst); +} + +static bool +has_nonremovable_reads(struct v3d_compile *c, struct qinst *inst) +{ + for (int i = 0; i < vir_get_nsrc(inst); i++) { + if (inst->src[i].file == QFILE_VPM) { + /* Instance ID, Vertex ID: Should have been removed at + * the NIR level + */ + if (inst->src[i].index == ~0) + return true; + + uint32_t attr = inst->src[i].index / 4; + uint32_t offset = inst->src[i].index % 4; + + if (c->vattr_sizes[attr] != offset) + return true; + + /* Can't get rid of the last VPM read, or the + * simulator (at least) throws an error. + */ + uint32_t total_size = 0; + for (uint32_t i = 0; i < ARRAY_SIZE(c->vattr_sizes); i++) + total_size += c->vattr_sizes[i]; + if (total_size == 1) + return true; + } + + /* Dead code removal of varyings is tricky, so just assert + * that it all happened at the NIR level. + */ + if (inst->src[i].file == QFILE_VARY) + return true; + } + + return false; +} + +bool +vir_opt_dead_code(struct v3d_compile *c) +{ + bool progress = false; + bool *used = calloc(c->num_temps, sizeof(bool)); + + vir_for_each_inst_inorder(inst, c) { + for (int i = 0; i < vir_get_nsrc(inst); i++) { + if (inst->src[i].file == QFILE_TEMP) + used[inst->src[i].index] = true; + } + } + + vir_for_each_block(block, c) { + vir_for_each_inst_safe(inst, block) { + if (inst->dst.file != QFILE_NULL && + !(inst->dst.file == QFILE_TEMP && + !used[inst->dst.index])) { + continue; + } + + if (vir_has_side_effects(c, inst)) + continue; + + if (inst->qpu.flags.apf != V3D_QPU_PF_NONE || + inst->qpu.flags.mpf != V3D_QPU_PF_NONE|| + has_nonremovable_reads(c, inst)) { + /* If we can't remove the instruction, but we + * don't need its destination value, just + * remove the destination. The register + * allocator would trivially color it and it + * wouldn't cause any register pressure, but + * it's nicer to read the VIR code without + * unused destination regs. + */ + if (inst->dst.file == QFILE_TEMP) { + if (debug) { + fprintf(stderr, + "Removing dst from: "); + vir_dump_inst(c, inst); + fprintf(stderr, "\n"); + } + c->defs[inst->dst.index] = NULL; + inst->dst.file = QFILE_NULL; + progress = true; + } + continue; + } + + for (int i = 0; i < vir_get_nsrc(inst); i++) { + if (inst->src[i].file != QFILE_VPM) + continue; + uint32_t attr = inst->src[i].index / 4; + uint32_t offset = (inst->src[i].index % 4); + + if (c->vattr_sizes[attr] == offset) { + c->num_inputs--; + c->vattr_sizes[attr]--; + } + } + + dce(c, inst); + progress = true; + continue; + } + } + + free(used); + + return progress; +} diff --git a/lib/mesa/src/broadcom/compiler/vir_register_allocate.c b/lib/mesa/src/broadcom/compiler/vir_register_allocate.c new file mode 100644 index 000000000..9ebf2cd69 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/vir_register_allocate.c @@ -0,0 +1,254 @@ +/* + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "util/ralloc.h" +#include "util/register_allocate.h" +#include "v3d_compiler.h" + +#define QPU_R(i) { .magic = false, .index = i } + +#define ACC_INDEX 0 +#define ACC_COUNT 5 +#define PHYS_INDEX (ACC_INDEX + ACC_COUNT) +#define PHYS_COUNT 64 + +bool +vir_init_reg_sets(struct v3d_compiler *compiler) +{ + compiler->regs = ra_alloc_reg_set(compiler, PHYS_INDEX + PHYS_COUNT, + true); + if (!compiler->regs) + return false; + + /* Allocate 3 regfile classes, for the ways the physical register file + * can be divided up for fragment shader threading. + */ + for (int threads = 0; threads < 3; threads++) { + compiler->reg_class[threads] = + ra_alloc_reg_class(compiler->regs); + + for (int i = PHYS_INDEX; + i < PHYS_INDEX + (PHYS_COUNT >> threads); i++) { + ra_class_add_reg(compiler->regs, + compiler->reg_class[threads], i); + } + + for (int i = ACC_INDEX + 0; i < ACC_INDEX + ACC_COUNT; i++) { + ra_class_add_reg(compiler->regs, + compiler->reg_class[threads], i); + } + } + + ra_set_finalize(compiler->regs, NULL); + + return true; +} + +struct node_to_temp_map { + uint32_t temp; + uint32_t priority; +}; + +static int +node_to_temp_priority(const void *in_a, const void *in_b) +{ + const struct node_to_temp_map *a = in_a; + const struct node_to_temp_map *b = in_b; + + return a->priority - b->priority; +} + +#define CLASS_BIT_PHYS (1 << 0) +#define CLASS_BIT_R0_R2 (1 << 1) +#define CLASS_BIT_R3 (1 << 2) +#define CLASS_BIT_R4 (1 << 3) + +/** + * Returns a mapping from QFILE_TEMP indices to struct qpu_regs. + * + * The return value should be freed by the caller. + */ +struct qpu_reg * +v3d_register_allocate(struct v3d_compile *c) +{ + struct node_to_temp_map map[c->num_temps]; + uint32_t temp_to_node[c->num_temps]; + uint8_t class_bits[c->num_temps]; + struct qpu_reg *temp_registers = calloc(c->num_temps, + sizeof(*temp_registers)); + int acc_nodes[ACC_COUNT]; + + struct ra_graph *g = ra_alloc_interference_graph(c->compiler->regs, + c->num_temps + + ARRAY_SIZE(acc_nodes)); + + /* Make some fixed nodes for the accumulators, which we will need to + * interfere with when ops have implied r3/r4 writes or for the thread + * switches. We could represent these as classes for the nodes to + * live in, but the classes take up a lot of memory to set up, so we + * don't want to make too many. + */ + for (int i = 0; i < ARRAY_SIZE(acc_nodes); i++) { + acc_nodes[i] = c->num_temps + i; + ra_set_node_reg(g, acc_nodes[i], ACC_INDEX + i); + } + + /* Compute the live ranges so we can figure out interference. */ + vir_calculate_live_intervals(c); + + for (uint32_t i = 0; i < c->num_temps; i++) { + map[i].temp = i; + map[i].priority = c->temp_end[i] - c->temp_start[i]; + } + qsort(map, c->num_temps, sizeof(map[0]), node_to_temp_priority); + for (uint32_t i = 0; i < c->num_temps; i++) { + temp_to_node[map[i].temp] = i; + } + + /* Figure out our register classes and preallocated registers. We + * start with any temp being able to be in any file, then instructions + * incrementally remove bits that the temp definitely can't be in. + */ + memset(class_bits, + CLASS_BIT_PHYS | CLASS_BIT_R0_R2 | CLASS_BIT_R3 | CLASS_BIT_R4, + sizeof(class_bits)); + + int ip = 0; + vir_for_each_inst_inorder(inst, c) { + /* If the instruction writes r3/r4 (and optionally moves its + * result to a temp), nothing else can be stored in r3/r4 across + * it. + */ + if (vir_writes_r3(inst)) { + for (int i = 0; i < c->num_temps; i++) { + if (c->temp_start[i] < ip && + c->temp_end[i] > ip) { + ra_add_node_interference(g, + temp_to_node[i], + acc_nodes[3]); + } + } + } + if (vir_writes_r4(inst)) { + for (int i = 0; i < c->num_temps; i++) { + if (c->temp_start[i] < ip && + c->temp_end[i] > ip) { + ra_add_node_interference(g, + temp_to_node[i], + acc_nodes[4]); + } + } + } + + if (inst->src[0].file == QFILE_REG) { + switch (inst->src[0].index) { + case 0: + case 1: + case 2: + /* Payload setup instructions: Force allocate + * the dst to the given register (so the MOV + * will disappear). + */ + assert(inst->qpu.alu.mul.op == V3D_QPU_M_MOV); + assert(inst->dst.file == QFILE_TEMP); + ra_set_node_reg(g, + temp_to_node[inst->dst.index], + PHYS_INDEX + + inst->src[0].index); + break; + } + } + +#if 0 + switch (inst->op) { + case QOP_THRSW: + /* All accumulators are invalidated across a thread + * switch. + */ + for (int i = 0; i < c->num_temps; i++) { + if (c->temp_start[i] < ip && c->temp_end[i] > ip) + class_bits[i] &= ~(CLASS_BIT_R0_R3 | + CLASS_BIT_R4); + } + break; + + default: + break; + } +#endif + + ip++; + } + + for (uint32_t i = 0; i < c->num_temps; i++) { + ra_set_node_class(g, temp_to_node[i], + c->compiler->reg_class[c->fs_threaded]); + } + + for (uint32_t i = 0; i < c->num_temps; i++) { + for (uint32_t j = i + 1; j < c->num_temps; j++) { + if (!(c->temp_start[i] >= c->temp_end[j] || + c->temp_start[j] >= c->temp_end[i])) { + ra_add_node_interference(g, + temp_to_node[i], + temp_to_node[j]); + } + } + } + + bool ok = ra_allocate(g); + if (!ok) { + if (!c->fs_threaded) { + fprintf(stderr, "Failed to register allocate:\n"); + vir_dump(c); + } + + c->failed = true; + free(temp_registers); + return NULL; + } + + for (uint32_t i = 0; i < c->num_temps; i++) { + int ra_reg = ra_get_node_reg(g, temp_to_node[i]); + if (ra_reg < PHYS_INDEX) { + temp_registers[i].magic = true; + temp_registers[i].index = (V3D_QPU_WADDR_R0 + + ra_reg - ACC_INDEX); + } else { + temp_registers[i].magic = false; + temp_registers[i].index = ra_reg - PHYS_INDEX; + } + + /* If the value's never used, just write to the NOP register + * for clarity in debug output. + */ + if (c->temp_start[i] == c->temp_end[i]) { + temp_registers[i].magic = true; + temp_registers[i].index = V3D_QPU_WADDR_NOP; + } + } + + ralloc_free(g); + + return temp_registers; +} diff --git a/lib/mesa/src/broadcom/compiler/vir_to_qpu.c b/lib/mesa/src/broadcom/compiler/vir_to_qpu.c new file mode 100644 index 000000000..eeb7b0bc2 --- /dev/null +++ b/lib/mesa/src/broadcom/compiler/vir_to_qpu.c @@ -0,0 +1,359 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "compiler/v3d_compiler.h" +#include "qpu/qpu_instr.h" +#include "qpu/qpu_disasm.h" + +static inline struct qpu_reg +qpu_reg(int index) +{ + struct qpu_reg reg = { + .magic = false, + .index = index, + }; + return reg; +} + +static inline struct qpu_reg +qpu_magic(enum v3d_qpu_waddr waddr) +{ + struct qpu_reg reg = { + .magic = true, + .index = waddr, + }; + return reg; +} + +static inline struct qpu_reg +qpu_acc(int acc) +{ + return qpu_magic(V3D_QPU_WADDR_R0 + acc); +} + +struct v3d_qpu_instr +v3d_qpu_nop(void) +{ + struct v3d_qpu_instr instr = { + .type = V3D_QPU_INSTR_TYPE_ALU, + .alu = { + .add = { + .op = V3D_QPU_A_NOP, + .waddr = V3D_QPU_WADDR_NOP, + .magic_write = true, + }, + .mul = { + .op = V3D_QPU_M_NOP, + .waddr = V3D_QPU_WADDR_NOP, + .magic_write = true, + }, + } + }; + + return instr; +} + +static struct qinst * +vir_nop(void) +{ + struct qreg undef = { QFILE_NULL, 0 }; + struct qinst *qinst = vir_add_inst(V3D_QPU_A_NOP, undef, undef, undef); + + return qinst; +} + +static struct qinst * +new_qpu_nop_before(struct qinst *inst) +{ + struct qinst *q = vir_nop(); + + list_addtail(&q->link, &inst->link); + + return q; +} + +static void +new_ldunif_instr(struct qinst *inst, int i) +{ + struct qinst *ldunif = new_qpu_nop_before(inst); + + ldunif->qpu.sig.ldunif = true; + assert(inst->src[i].file == QFILE_UNIF); + ldunif->uniform = inst->src[i].index; +} + +/** + * Allocates the src register (accumulator or register file) into the RADDR + * fields of the instruction. + */ +static void +set_src(struct v3d_qpu_instr *instr, enum v3d_qpu_mux *mux, struct qpu_reg src) +{ + if (src.magic) { + assert(src.index >= V3D_QPU_WADDR_R0 && + src.index <= V3D_QPU_WADDR_R5); + *mux = src.index - V3D_QPU_WADDR_R0 + V3D_QPU_MUX_R0; + return; + } + + if (instr->alu.add.a != V3D_QPU_MUX_A && + instr->alu.add.b != V3D_QPU_MUX_A && + instr->alu.mul.a != V3D_QPU_MUX_A && + instr->alu.mul.b != V3D_QPU_MUX_A) { + instr->raddr_a = src.index; + *mux = V3D_QPU_MUX_A; + } else { + if (instr->raddr_a == src.index) { + *mux = V3D_QPU_MUX_A; + } else { + assert(!(instr->alu.add.a == V3D_QPU_MUX_B && + instr->alu.add.b == V3D_QPU_MUX_B && + instr->alu.mul.a == V3D_QPU_MUX_B && + instr->alu.mul.b == V3D_QPU_MUX_B) || + src.index == instr->raddr_b); + + instr->raddr_b = src.index; + *mux = V3D_QPU_MUX_B; + } + } +} + +static void +v3d_generate_code_block(struct v3d_compile *c, + struct qblock *block, + struct qpu_reg *temp_registers) +{ + int last_vpm_read_index = -1; + + vir_for_each_inst(qinst, block) { +#if 0 + fprintf(stderr, "translating qinst to qpu: "); + vir_dump_inst(c, qinst); + fprintf(stderr, "\n"); +#endif + + struct qinst *temp; + + if (vir_has_implicit_uniform(qinst)) { + int src = vir_get_implicit_uniform_src(qinst); + assert(qinst->src[src].file == QFILE_UNIF); + qinst->uniform = qinst->src[src].index; + c->num_uniforms++; + } + + int nsrc = vir_get_non_sideband_nsrc(qinst); + struct qpu_reg src[ARRAY_SIZE(qinst->src)]; + bool emitted_ldunif = false; + for (int i = 0; i < nsrc; i++) { + int index = qinst->src[i].index; + switch (qinst->src[i].file) { + case QFILE_REG: + src[i] = qpu_reg(qinst->src[i].index); + break; + case QFILE_MAGIC: + src[i] = qpu_magic(qinst->src[i].index); + break; + case QFILE_NULL: + case QFILE_LOAD_IMM: + src[i] = qpu_acc(0); + break; + case QFILE_TEMP: + src[i] = temp_registers[index]; + break; + case QFILE_UNIF: + if (!emitted_ldunif) { + new_ldunif_instr(qinst, i); + c->num_uniforms++; + emitted_ldunif = true; + } + + src[i] = qpu_acc(5); + break; + case QFILE_VARY: + temp = new_qpu_nop_before(qinst); + temp->qpu.sig.ldvary = true; + + src[i] = qpu_acc(3); + break; + case QFILE_SMALL_IMM: + abort(); /* XXX */ +#if 0 + src[i].mux = QPU_MUX_SMALL_IMM; + src[i].addr = qpu_encode_small_immediate(qinst->src[i].index); + /* This should only have returned a valid + * small immediate field, not ~0 for failure. + */ + assert(src[i].addr <= 47); +#endif + break; + + case QFILE_VPM: + assert((int)qinst->src[i].index >= + last_vpm_read_index); + (void)last_vpm_read_index; + last_vpm_read_index = qinst->src[i].index; + + temp = new_qpu_nop_before(qinst); + temp->qpu.sig.ldvpm = true; + + src[i] = qpu_acc(3); + break; + + case QFILE_TLB: + case QFILE_TLBU: + unreachable("bad vir src file"); + } + } + + struct qpu_reg dst; + switch (qinst->dst.file) { + case QFILE_NULL: + dst = qpu_magic(V3D_QPU_WADDR_NOP); + break; + + case QFILE_REG: + dst = qpu_reg(qinst->dst.index); + break; + + case QFILE_MAGIC: + dst = qpu_magic(qinst->dst.index); + break; + + case QFILE_TEMP: + dst = temp_registers[qinst->dst.index]; + break; + + case QFILE_VPM: + dst = qpu_magic(V3D_QPU_WADDR_VPM); + break; + + case QFILE_TLB: + dst = qpu_magic(V3D_QPU_WADDR_TLB); + break; + + case QFILE_TLBU: + dst = qpu_magic(V3D_QPU_WADDR_TLBU); + break; + + case QFILE_VARY: + case QFILE_UNIF: + case QFILE_SMALL_IMM: + case QFILE_LOAD_IMM: + assert(!"not reached"); + break; + } + + if (qinst->qpu.type == V3D_QPU_INSTR_TYPE_ALU) { + if (qinst->qpu.alu.add.op != V3D_QPU_A_NOP) { + assert(qinst->qpu.alu.mul.op == V3D_QPU_M_NOP); + if (nsrc >= 1) { + set_src(&qinst->qpu, + &qinst->qpu.alu.add.a, src[0]); + } + if (nsrc >= 2) { + set_src(&qinst->qpu, + &qinst->qpu.alu.add.b, src[1]); + } + + qinst->qpu.alu.add.waddr = dst.index; + qinst->qpu.alu.add.magic_write = dst.magic; + } else { + if (nsrc >= 1) { + set_src(&qinst->qpu, + &qinst->qpu.alu.mul.a, src[0]); + } + if (nsrc >= 2) { + set_src(&qinst->qpu, + &qinst->qpu.alu.mul.b, src[1]); + } + + qinst->qpu.alu.mul.waddr = dst.index; + qinst->qpu.alu.mul.magic_write = dst.magic; + } + } else { + assert(qinst->qpu.type == V3D_QPU_INSTR_TYPE_BRANCH); + } + } +} + + +static void +v3d_dump_qpu(struct v3d_compile *c) +{ + fprintf(stderr, "%s prog %d/%d QPU:\n", + vir_get_stage_name(c), + c->program_id, c->variant_id); + + for (int i = 0; i < c->qpu_inst_count; i++) { + const char *str = v3d_qpu_disasm(c->devinfo, c->qpu_insts[i]); + fprintf(stderr, "0x%016"PRIx64" %s\n", c->qpu_insts[i], str); + } + fprintf(stderr, "\n"); +} + +void +v3d_vir_to_qpu(struct v3d_compile *c) +{ + struct qpu_reg *temp_registers = v3d_register_allocate(c); + struct qblock *end_block = list_last_entry(&c->blocks, + struct qblock, link); + + /* Reset the uniform count to how many will be actually loaded by the + * generated QPU code. + */ + c->num_uniforms = 0; + + vir_for_each_block(block, c) + v3d_generate_code_block(c, block, temp_registers); + + struct qinst *thrsw = vir_nop(); + list_addtail(&thrsw->link, &end_block->instructions); + thrsw->qpu.sig.thrsw = true; + + uint32_t cycles = v3d_qpu_schedule_instructions(c); + + c->qpu_insts = rzalloc_array(c, uint64_t, c->qpu_inst_count); + int i = 0; + vir_for_each_inst_inorder(inst, c) { + bool ok = v3d_qpu_instr_pack(c->devinfo, &inst->qpu, + &c->qpu_insts[i++]); + assert(ok); (void) ok; + } + assert(i == c->qpu_inst_count); + + if (V3D_DEBUG & V3D_DEBUG_SHADERDB) { + fprintf(stderr, "SHADER-DB: %s prog %d/%d: %d estimated cycles\n", + vir_get_stage_name(c), + c->program_id, c->variant_id, + cycles); + } + + if (V3D_DEBUG & (V3D_DEBUG_QPU | + v3d_debug_flag_for_shader_stage(c->s->info.stage))) { + v3d_dump_qpu(c); + } + + qpu_validate(c); + + free(temp_registers); +} diff --git a/lib/mesa/src/broadcom/qpu/qpu_disasm.c b/lib/mesa/src/broadcom/qpu/qpu_disasm.c new file mode 100644 index 000000000..5ee834852 --- /dev/null +++ b/lib/mesa/src/broadcom/qpu/qpu_disasm.c @@ -0,0 +1,298 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <string.h> +#include <stdio.h> +#include "util/ralloc.h" + +#include "broadcom/common/v3d_device_info.h" +#include "qpu_instr.h" +#include "qpu_disasm.h" + +struct disasm_state { + const struct v3d_device_info *devinfo; + char *string; + size_t offset; +}; + +static void +append(struct disasm_state *disasm, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + ralloc_vasprintf_rewrite_tail(&disasm->string, + &disasm->offset, + fmt, args); + va_end(args); +} + +static void +pad_to(struct disasm_state *disasm, int n) +{ + /* FIXME: Do a single append somehow. */ + while (disasm->offset < n) + append(disasm, " "); +} + + +static void +v3d_qpu_disasm_raddr(struct disasm_state *disasm, + const struct v3d_qpu_instr *instr, uint8_t mux) +{ + if (mux == V3D_QPU_MUX_A) { + append(disasm, "rf%d", instr->raddr_a); + } else if (mux == V3D_QPU_MUX_B) { + append(disasm, "rf%d", instr->raddr_b); + } else { + append(disasm, "r%d", mux); + } +} + +static void +v3d_qpu_disasm_waddr(struct disasm_state *disasm, uint32_t waddr, bool magic) +{ + if (!magic) { + append(disasm, "rf%d", waddr); + return; + } + + const char *name = v3d_qpu_magic_waddr_name(waddr); + if (name) + append(disasm, "%s", name); + else + append(disasm, "waddr UNKNOWN %d", waddr); +} + +static void +v3d_qpu_disasm_add(struct disasm_state *disasm, + const struct v3d_qpu_instr *instr) +{ + bool has_dst = v3d_qpu_add_op_has_dst(instr->alu.add.op); + int num_src = v3d_qpu_add_op_num_src(instr->alu.add.op); + + append(disasm, "%s", v3d_qpu_add_op_name(instr->alu.add.op)); + append(disasm, "%s", v3d_qpu_cond_name(instr->flags.ac)); + append(disasm, "%s", v3d_qpu_pf_name(instr->flags.apf)); + append(disasm, "%s", v3d_qpu_uf_name(instr->flags.auf)); + + append(disasm, " "); + + if (has_dst) { + v3d_qpu_disasm_waddr(disasm, instr->alu.add.waddr, + instr->alu.add.magic_write); + append(disasm, v3d_qpu_pack_name(instr->alu.add.output_pack)); + } + + if (num_src >= 1) { + if (has_dst) + append(disasm, ", "); + v3d_qpu_disasm_raddr(disasm, instr, instr->alu.add.a); + append(disasm, "%s", + v3d_qpu_unpack_name(instr->alu.add.a_unpack)); + } + + if (num_src >= 2) { + append(disasm, ", "); + v3d_qpu_disasm_raddr(disasm, instr, instr->alu.add.b); + append(disasm, "%s", + v3d_qpu_unpack_name(instr->alu.add.b_unpack)); + } +} + +static void +v3d_qpu_disasm_mul(struct disasm_state *disasm, + const struct v3d_qpu_instr *instr) +{ + bool has_dst = v3d_qpu_mul_op_has_dst(instr->alu.mul.op); + int num_src = v3d_qpu_mul_op_num_src(instr->alu.mul.op); + + pad_to(disasm, 21); + append(disasm, "; "); + + append(disasm, "%s", v3d_qpu_mul_op_name(instr->alu.mul.op)); + append(disasm, "%s", v3d_qpu_cond_name(instr->flags.mc)); + append(disasm, "%s", v3d_qpu_pf_name(instr->flags.mpf)); + append(disasm, "%s", v3d_qpu_uf_name(instr->flags.muf)); + + if (instr->alu.mul.op == V3D_QPU_M_NOP) + return; + + append(disasm, " "); + + if (has_dst) { + v3d_qpu_disasm_waddr(disasm, instr->alu.mul.waddr, + instr->alu.mul.magic_write); + append(disasm, v3d_qpu_pack_name(instr->alu.mul.output_pack)); + } + + if (num_src >= 1) { + if (has_dst) + append(disasm, ", "); + v3d_qpu_disasm_raddr(disasm, instr, instr->alu.mul.a); + append(disasm, "%s", + v3d_qpu_unpack_name(instr->alu.mul.a_unpack)); + } + + if (num_src >= 2) { + append(disasm, ", "); + v3d_qpu_disasm_raddr(disasm, instr, instr->alu.mul.b); + append(disasm, "%s", + v3d_qpu_unpack_name(instr->alu.mul.b_unpack)); + } +} + +static void +v3d_qpu_disasm_sig(struct disasm_state *disasm, + const struct v3d_qpu_instr *instr) +{ + const struct v3d_qpu_sig *sig = &instr->sig; + + if (!sig->thrsw && + !sig->ldvary && + !sig->ldvpm && + !sig->ldtmu && + !sig->ldunif && + !sig->wrtmuc) { + return; + } + + pad_to(disasm, 41); + + if (sig->thrsw) + append(disasm, "; thrsw"); + if (sig->ldvary) + append(disasm, "; ldvary"); + if (sig->ldvpm) + append(disasm, "; ldvpm"); + if (sig->ldtmu) + append(disasm, "; ldtmu"); + if (sig->ldunif) + append(disasm, "; ldunif"); + if (sig->wrtmuc) + append(disasm, "; wrtmuc"); +} + +static void +v3d_qpu_disasm_alu(struct disasm_state *disasm, + const struct v3d_qpu_instr *instr) +{ + v3d_qpu_disasm_add(disasm, instr); + v3d_qpu_disasm_mul(disasm, instr); + v3d_qpu_disasm_sig(disasm, instr); +} + +static void +v3d_qpu_disasm_branch(struct disasm_state *disasm, + const struct v3d_qpu_instr *instr) +{ + append(disasm, "b"); + if (instr->branch.ub) + append(disasm, "u"); + append(disasm, "%s", v3d_qpu_branch_cond_name(instr->branch.cond)); + append(disasm, "%s", v3d_qpu_msfign_name(instr->branch.msfign)); + + switch (instr->branch.bdi) { + case V3D_QPU_BRANCH_DEST_ABS: + append(disasm, " zero_addr+0x%08x", instr->branch.offset); + break; + + case V3D_QPU_BRANCH_DEST_REL: + append(disasm, " %d", instr->branch.offset); + break; + + case V3D_QPU_BRANCH_DEST_LINK_REG: + append(disasm, " lri"); + break; + + case V3D_QPU_BRANCH_DEST_REGFILE: + append(disasm, " rf%d", instr->branch.raddr_a); + break; + } + + if (instr->branch.ub) { + switch (instr->branch.bdu) { + case V3D_QPU_BRANCH_DEST_ABS: + append(disasm, ", a:unif"); + break; + + case V3D_QPU_BRANCH_DEST_REL: + append(disasm, ", r:unif"); + break; + + case V3D_QPU_BRANCH_DEST_LINK_REG: + append(disasm, ", lri"); + break; + + case V3D_QPU_BRANCH_DEST_REGFILE: + append(disasm, ", rf%d", instr->branch.raddr_a); + break; + } + } +} + +const char * +v3d_qpu_decode(const struct v3d_device_info *devinfo, + const struct v3d_qpu_instr *instr) +{ + struct disasm_state disasm = { + .string = rzalloc_size(NULL, 1), + .offset = 0, + .devinfo = devinfo, + }; + + switch (instr->type) { + case V3D_QPU_INSTR_TYPE_ALU: + v3d_qpu_disasm_alu(&disasm, instr); + break; + + case V3D_QPU_INSTR_TYPE_BRANCH: + v3d_qpu_disasm_branch(&disasm, instr); + break; + } + + return disasm.string; +} + +/** + * Returns a string containing the disassembled representation of the QPU + * instruction. It is the caller's responsibility to free the return value + * with ralloc_free(). + */ +const char * +v3d_qpu_disasm(const struct v3d_device_info *devinfo, uint64_t inst) +{ + struct v3d_qpu_instr instr; + bool ok = v3d_qpu_instr_unpack(devinfo, inst, &instr); + assert(ok); (void)ok; + + return v3d_qpu_decode(devinfo, &instr); +} + +void +v3d_qpu_dump(const struct v3d_device_info *devinfo, + const struct v3d_qpu_instr *instr) +{ + const char *decoded = v3d_qpu_decode(devinfo, instr); + fprintf(stderr, "%s", decoded); + ralloc_free((char *)decoded); +} diff --git a/lib/mesa/src/broadcom/qpu/qpu_disasm.h b/lib/mesa/src/broadcom/qpu/qpu_disasm.h new file mode 100644 index 000000000..efdf8ddb5 --- /dev/null +++ b/lib/mesa/src/broadcom/qpu/qpu_disasm.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 VC5_QPU_DISASM_H +#define VC5_QPU_DISASM_H + +#include "broadcom/common/v3d_device_info.h" + +struct v3d_qpu_instr; + +const char *v3d_qpu_decode(const struct v3d_device_info *devinfo, const + struct v3d_qpu_instr *instr); + +const char *v3d_qpu_disasm(const struct v3d_device_info *devinfo, uint64_t inst); + +void v3d_qpu_dump(const struct v3d_device_info *devinfo, const + struct v3d_qpu_instr *instr); + +#endif /* VC5_QPU_DISASM_H */ diff --git a/lib/mesa/src/broadcom/qpu/qpu_instr.c b/lib/mesa/src/broadcom/qpu/qpu_instr.c new file mode 100644 index 000000000..7499170de --- /dev/null +++ b/lib/mesa/src/broadcom/qpu/qpu_instr.c @@ -0,0 +1,645 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <stdlib.h> +#include "util/macros.h" +#include "qpu_instr.h" + +#ifndef QPU_MASK +#define QPU_MASK(high, low) ((((uint64_t)1<<((high)-(low)+1))-1)<<(low)) +/* Using the GNU statement expression extension */ +#define QPU_SET_FIELD(value, field) \ + ({ \ + uint64_t fieldval = (uint64_t)(value) << field ## _SHIFT; \ + assert((fieldval & ~ field ## _MASK) == 0); \ + fieldval & field ## _MASK; \ + }) + +#define QPU_GET_FIELD(word, field) ((uint32_t)(((word) & field ## _MASK) >> field ## _SHIFT)) + +#define QPU_UPDATE_FIELD(inst, value, field) \ + (((inst) & ~(field ## _MASK)) | QPU_SET_FIELD(value, field)) +#endif /* QPU_MASK */ + +#define VC5_QPU_OP_MUL_SHIFT 58 +#define VC5_QPU_OP_MUL_MASK QPU_MASK(63, 58) + +#define VC5_QPU_SIG_SHIFT 53 +#define VC5_QPU_SIG_MASK QPU_MASK(57, 53) +# define VC5_QPU_SIG_THRSW_BIT 0x1 +# define VC5_QPU_SIG_LDUNIF_BIT 0x2 +# define VC5_QPU_SIG_LDTMU_BIT 0x4 +# define VC5_QPU_SIG_LDVARY_BIT 0x8 + +#define VC5_QPU_COND_SHIFT 46 +#define VC5_QPU_COND_MASK QPU_MASK(52, 46) + +#define VC5_QPU_COND_IFA 0 +#define VC5_QPU_COND_IFB 1 +#define VC5_QPU_COND_IFNA 2 +#define VC5_QPU_COND_IFNB 3 + +#define VC5_QPU_MM QPU_MASK(45, 45) +#define VC5_QPU_MA QPU_MASK(44, 44) + +#define V3D_QPU_WADDR_M_SHIFT 38 +#define V3D_QPU_WADDR_M_MASK QPU_MASK(43, 38) + +#define VC5_QPU_BRANCH_ADDR_LOW_SHIFT 35 +#define VC5_QPU_BRANCH_ADDR_LOW_MASK QPU_MASK(55, 35) + +#define V3D_QPU_WADDR_A_SHIFT 32 +#define V3D_QPU_WADDR_A_MASK QPU_MASK(37, 32) + +#define VC5_QPU_BRANCH_COND_SHIFT 32 +#define VC5_QPU_BRANCH_COND_MASK QPU_MASK(34, 32) + +#define VC5_QPU_BRANCH_ADDR_HIGH_SHIFT 24 +#define VC5_QPU_BRANCH_ADDR_HIGH_MASK QPU_MASK(31, 24) + +#define VC5_QPU_OP_ADD_SHIFT 24 +#define VC5_QPU_OP_ADD_MASK QPU_MASK(31, 24) + +#define VC5_QPU_MUL_B_SHIFT 21 +#define VC5_QPU_MUL_B_MASK QPU_MASK(23, 21) + +#define VC5_QPU_BRANCH_MSFIGN_SHIFT 21 +#define VC5_QPU_BRANCH_MSFIGN_MASK QPU_MASK(22, 21) + +#define VC5_QPU_MUL_A_SHIFT 18 +#define VC5_QPU_MUL_A_MASK QPU_MASK(20, 18) + +#define VC5_QPU_ADD_B_SHIFT 15 +#define VC5_QPU_ADD_B_MASK QPU_MASK(17, 15) + +#define VC5_QPU_BRANCH_BDU_SHIFT 15 +#define VC5_QPU_BRANCH_BDU_MASK QPU_MASK(17, 15) + +#define VC5_QPU_BRANCH_UB QPU_MASK(14, 14) + +#define VC5_QPU_ADD_A_SHIFT 12 +#define VC5_QPU_ADD_A_MASK QPU_MASK(14, 12) + +#define VC5_QPU_BRANCH_BDI_SHIFT 12 +#define VC5_QPU_BRANCH_BDI_MASK QPU_MASK(13, 12) + +#define VC5_QPU_RADDR_A_SHIFT 6 +#define VC5_QPU_RADDR_A_MASK QPU_MASK(11, 6) + +#define VC5_QPU_RADDR_B_SHIFT 0 +#define VC5_QPU_RADDR_B_MASK QPU_MASK(5, 0) + +const char * +v3d_qpu_magic_waddr_name(enum v3d_qpu_waddr waddr) +{ + static const char *waddr_magic[] = { + [V3D_QPU_WADDR_R0] = "r0", + [V3D_QPU_WADDR_R1] = "r1", + [V3D_QPU_WADDR_R2] = "r2", + [V3D_QPU_WADDR_R3] = "r3", + [V3D_QPU_WADDR_R4] = "r4", + [V3D_QPU_WADDR_R5] = "r5", + [V3D_QPU_WADDR_NOP] = "-", + [V3D_QPU_WADDR_TLB] = "tlb", + [V3D_QPU_WADDR_TLBU] = "tlbu", + [V3D_QPU_WADDR_TMU] = "tmu", + [V3D_QPU_WADDR_TMUL] = "tmul", + [V3D_QPU_WADDR_TMUD] = "tmud", + [V3D_QPU_WADDR_TMUA] = "tmua", + [V3D_QPU_WADDR_TMUAU] = "tmuau", + [V3D_QPU_WADDR_VPM] = "vpm", + [V3D_QPU_WADDR_VPMU] = "vpmu", + [V3D_QPU_WADDR_SYNC] = "sync", + [V3D_QPU_WADDR_SYNCU] = "syncu", + [V3D_QPU_WADDR_RECIP] = "recip", + [V3D_QPU_WADDR_RSQRT] = "rsqrt", + [V3D_QPU_WADDR_EXP] = "exp", + [V3D_QPU_WADDR_LOG] = "log", + [V3D_QPU_WADDR_SIN] = "sin", + [V3D_QPU_WADDR_RSQRT2] = "rsqrt2", + }; + + return waddr_magic[waddr]; +} + +const char * +v3d_qpu_add_op_name(enum v3d_qpu_add_op op) +{ + static const char *op_names[] = { + [V3D_QPU_A_FADD] = "fadd", + [V3D_QPU_A_FADDNF] = "faddnf", + [V3D_QPU_A_VFPACK] = "vfpack", + [V3D_QPU_A_ADD] = "add", + [V3D_QPU_A_SUB] = "sub", + [V3D_QPU_A_FSUB] = "fsub", + [V3D_QPU_A_MIN] = "min", + [V3D_QPU_A_MAX] = "max", + [V3D_QPU_A_UMIN] = "umin", + [V3D_QPU_A_UMAX] = "umax", + [V3D_QPU_A_SHL] = "shl", + [V3D_QPU_A_SHR] = "shr", + [V3D_QPU_A_ASR] = "asr", + [V3D_QPU_A_ROR] = "ror", + [V3D_QPU_A_FMIN] = "fmin", + [V3D_QPU_A_FMAX] = "fmax", + [V3D_QPU_A_VFMIN] = "vfmin", + [V3D_QPU_A_AND] = "and", + [V3D_QPU_A_OR] = "or", + [V3D_QPU_A_XOR] = "xor", + [V3D_QPU_A_VADD] = "vadd", + [V3D_QPU_A_VSUB] = "vsub", + [V3D_QPU_A_NOT] = "not", + [V3D_QPU_A_NEG] = "neg", + [V3D_QPU_A_FLAPUSH] = "flapush", + [V3D_QPU_A_FLBPUSH] = "flbpush", + [V3D_QPU_A_FLBPOP] = "flbpop", + [V3D_QPU_A_SETMSF] = "setmsf", + [V3D_QPU_A_SETREVF] = "setrevf", + [V3D_QPU_A_NOP] = "nop", + [V3D_QPU_A_TIDX] = "tidx", + [V3D_QPU_A_EIDX] = "eidx", + [V3D_QPU_A_LR] = "lr", + [V3D_QPU_A_VFLA] = "vfla", + [V3D_QPU_A_VFLNA] = "vflna", + [V3D_QPU_A_VFLB] = "vflb", + [V3D_QPU_A_VFLNB] = "vflnb", + [V3D_QPU_A_FXCD] = "fxcd", + [V3D_QPU_A_XCD] = "xcd", + [V3D_QPU_A_FYCD] = "fycd", + [V3D_QPU_A_YCD] = "ycd", + [V3D_QPU_A_MSF] = "msf", + [V3D_QPU_A_REVF] = "revf", + [V3D_QPU_A_VDWWT] = "vdwwt", + [V3D_QPU_A_IID] = "iid", + [V3D_QPU_A_SAMPID] = "sampid", + [V3D_QPU_A_PATCHID] = "patchid", + [V3D_QPU_A_TMUWT] = "tmuwt", + [V3D_QPU_A_VPMSETUP] = "vpmsetup", + [V3D_QPU_A_VPMWT] = "vpmwt", + [V3D_QPU_A_LDVPMV] = "ldvpmv", + [V3D_QPU_A_LDVPMD] = "ldvpmd", + [V3D_QPU_A_LDVPMP] = "ldvpmp", + [V3D_QPU_A_LDVPMG] = "ldvpmg", + [V3D_QPU_A_FCMP] = "fcmp", + [V3D_QPU_A_VFMAX] = "vfmax", + [V3D_QPU_A_FROUND] = "fround", + [V3D_QPU_A_FTOIN] = "ftoin", + [V3D_QPU_A_FTRUNC] = "ftrunc", + [V3D_QPU_A_FTOIZ] = "ftoiz", + [V3D_QPU_A_FFLOOR] = "ffloor", + [V3D_QPU_A_FTOUZ] = "ftouz", + [V3D_QPU_A_FCEIL] = "fceil", + [V3D_QPU_A_FTOC] = "ftoc", + [V3D_QPU_A_FDX] = "fdx", + [V3D_QPU_A_FDY] = "fdy", + [V3D_QPU_A_STVPMV] = "stvpmv", + [V3D_QPU_A_STVPMD] = "stvpmd", + [V3D_QPU_A_STVPMP] = "stvpmp", + [V3D_QPU_A_ITOF] = "itof", + [V3D_QPU_A_CLZ] = "clz", + [V3D_QPU_A_UTOF] = "utof", + }; + + if (op >= ARRAY_SIZE(op_names)) + return NULL; + + return op_names[op]; +} + +const char * +v3d_qpu_mul_op_name(enum v3d_qpu_mul_op op) +{ + static const char *op_names[] = { + [V3D_QPU_M_ADD] = "add", + [V3D_QPU_M_SUB] = "sub", + [V3D_QPU_M_UMUL24] = "umul24", + [V3D_QPU_M_VFMUL] = "vfmul", + [V3D_QPU_M_SMUL24] = "smul24", + [V3D_QPU_M_MULTOP] = "multop", + [V3D_QPU_M_FMOV] = "fmov", + [V3D_QPU_M_MOV] = "mov", + [V3D_QPU_M_NOP] = "nop", + [V3D_QPU_M_FMUL] = "fmul", + }; + + if (op >= ARRAY_SIZE(op_names)) + return NULL; + + return op_names[op]; +} + +const char * +v3d_qpu_cond_name(enum v3d_qpu_cond cond) +{ + switch (cond) { + case V3D_QPU_COND_NONE: + return ""; + case V3D_QPU_COND_IFA: + return ".ifa"; + case V3D_QPU_COND_IFB: + return ".ifb"; + case V3D_QPU_COND_IFNA: + return ".ifna"; + case V3D_QPU_COND_IFNB: + return ".ifnb"; + default: + unreachable("bad cond value"); + } +} + +const char * +v3d_qpu_branch_cond_name(enum v3d_qpu_branch_cond cond) +{ + switch (cond) { + case V3D_QPU_BRANCH_COND_ALWAYS: + return ""; + case V3D_QPU_BRANCH_COND_A0: + return ".a0"; + case V3D_QPU_BRANCH_COND_NA0: + return ".na0"; + case V3D_QPU_BRANCH_COND_ALLA: + return ".alla"; + case V3D_QPU_BRANCH_COND_ANYNA: + return ".anyna"; + case V3D_QPU_BRANCH_COND_ANYA: + return ".anya"; + case V3D_QPU_BRANCH_COND_ALLNA: + return ".allna"; + default: + unreachable("bad branch cond value"); + } +} + +const char * +v3d_qpu_msfign_name(enum v3d_qpu_msfign msfign) +{ + switch (msfign) { + case V3D_QPU_MSFIGN_NONE: + return ""; + case V3D_QPU_MSFIGN_P: + return "p"; + case V3D_QPU_MSFIGN_Q: + return "q"; + default: + unreachable("bad branch cond value"); + } +} + +const char * +v3d_qpu_pf_name(enum v3d_qpu_pf pf) +{ + switch (pf) { + case V3D_QPU_PF_NONE: + return ""; + case V3D_QPU_PF_PUSHZ: + return ".pushz"; + case V3D_QPU_PF_PUSHN: + return ".pushn"; + case V3D_QPU_PF_PUSHC: + return ".pushc"; + default: + unreachable("bad pf value"); + } +} + +const char * +v3d_qpu_uf_name(enum v3d_qpu_uf uf) +{ + switch (uf) { + case V3D_QPU_UF_NONE: + return ""; + case V3D_QPU_UF_ANDZ: + return ".andz"; + case V3D_QPU_UF_ANDNZ: + return ".andnz"; + case V3D_QPU_UF_NORZ: + return ".norz"; + case V3D_QPU_UF_NORNZ: + return ".nornz"; + case V3D_QPU_UF_ANDN: + return ".andn"; + case V3D_QPU_UF_ANDNN: + return ".andnn"; + case V3D_QPU_UF_NORN: + return ".norn"; + case V3D_QPU_UF_NORNN: + return ".nornn"; + case V3D_QPU_UF_ANDC: + return ".andc"; + case V3D_QPU_UF_ANDNC: + return ".andnc"; + case V3D_QPU_UF_NORC: + return ".norc"; + case V3D_QPU_UF_NORNC: + return ".nornc"; + default: + unreachable("bad pf value"); + } +} + +const char * +v3d_qpu_pack_name(enum v3d_qpu_output_pack pack) +{ + switch (pack) { + case V3D_QPU_PACK_NONE: + return ""; + case V3D_QPU_PACK_L: + return ".l"; + case V3D_QPU_PACK_H: + return ".h"; + default: + unreachable("bad pack value"); + } +} + +const char * +v3d_qpu_unpack_name(enum v3d_qpu_input_unpack unpack) +{ + switch (unpack) { + case V3D_QPU_UNPACK_NONE: + return ""; + case V3D_QPU_UNPACK_L: + return ".l"; + case V3D_QPU_UNPACK_H: + return ".h"; + case V3D_QPU_UNPACK_ABS: + return ".abs"; + case V3D_QPU_UNPACK_REPLICATE_32F_16: + return ".ff"; + case V3D_QPU_UNPACK_REPLICATE_L_16: + return ".ll"; + case V3D_QPU_UNPACK_REPLICATE_H_16: + return ".hh"; + case V3D_QPU_UNPACK_SWAP_16: + return ".swp"; + default: + unreachable("bad unpack value"); + } +} + +#define D 1 +#define A 2 +#define B 4 +static const uint8_t add_op_args[] = { + [V3D_QPU_A_FADD] = D | A | B, + [V3D_QPU_A_FADDNF] = D | A | B, + [V3D_QPU_A_VFPACK] = D | A | B, + [V3D_QPU_A_ADD] = D | A | B, + [V3D_QPU_A_VFPACK] = D | A | B, + [V3D_QPU_A_SUB] = D | A | B, + [V3D_QPU_A_VFPACK] = D | A | B, + [V3D_QPU_A_FSUB] = D | A | B, + [V3D_QPU_A_MIN] = D | A | B, + [V3D_QPU_A_MAX] = D | A | B, + [V3D_QPU_A_UMIN] = D | A | B, + [V3D_QPU_A_UMAX] = D | A | B, + [V3D_QPU_A_SHL] = D | A | B, + [V3D_QPU_A_SHR] = D | A | B, + [V3D_QPU_A_ASR] = D | A | B, + [V3D_QPU_A_ROR] = D | A | B, + [V3D_QPU_A_FMIN] = D | A | B, + [V3D_QPU_A_FMAX] = D | A | B, + [V3D_QPU_A_VFMIN] = D | A | B, + + [V3D_QPU_A_AND] = D | A | B, + [V3D_QPU_A_OR] = D | A | B, + [V3D_QPU_A_XOR] = D | A | B, + + [V3D_QPU_A_VADD] = D | A | B, + [V3D_QPU_A_VSUB] = D | A | B, + [V3D_QPU_A_NOT] = D | A, + [V3D_QPU_A_NEG] = D | A, + [V3D_QPU_A_FLAPUSH] = D | A, + [V3D_QPU_A_FLBPUSH] = D | A, + [V3D_QPU_A_FLBPOP] = D | A, + [V3D_QPU_A_SETMSF] = D | A, + [V3D_QPU_A_SETREVF] = D | A, + [V3D_QPU_A_NOP] = 0, + [V3D_QPU_A_TIDX] = D, + [V3D_QPU_A_EIDX] = D, + [V3D_QPU_A_LR] = D, + [V3D_QPU_A_VFLA] = D, + [V3D_QPU_A_VFLNA] = D, + [V3D_QPU_A_VFLB] = D, + [V3D_QPU_A_VFLNB] = D, + + [V3D_QPU_A_FXCD] = D, + [V3D_QPU_A_XCD] = D, + [V3D_QPU_A_FYCD] = D, + [V3D_QPU_A_YCD] = D, + + [V3D_QPU_A_MSF] = D, + [V3D_QPU_A_REVF] = D, + [V3D_QPU_A_VDWWT] = D, + [V3D_QPU_A_IID] = D, + [V3D_QPU_A_SAMPID] = D, + [V3D_QPU_A_PATCHID] = D, + [V3D_QPU_A_TMUWT] = D, + [V3D_QPU_A_VPMWT] = D, + + [V3D_QPU_A_VPMSETUP] = D | A, + + [V3D_QPU_A_LDVPMV] = D | A, + [V3D_QPU_A_LDVPMD] = D | A, + [V3D_QPU_A_LDVPMP] = D | A, + [V3D_QPU_A_LDVPMG] = D | A | B, + + /* FIXME: MOVABSNEG */ + + [V3D_QPU_A_FCMP] = D | A | B, + [V3D_QPU_A_VFMAX] = D | A | B, + + [V3D_QPU_A_FROUND] = D | A, + [V3D_QPU_A_FTOIN] = D | A, + [V3D_QPU_A_FTRUNC] = D | A, + [V3D_QPU_A_FTOIZ] = D | A, + [V3D_QPU_A_FFLOOR] = D | A, + [V3D_QPU_A_FTOUZ] = D | A, + [V3D_QPU_A_FCEIL] = D | A, + [V3D_QPU_A_FTOC] = D | A, + + [V3D_QPU_A_FDX] = D | A, + [V3D_QPU_A_FDY] = D | A, + + [V3D_QPU_A_STVPMV] = A | B, + [V3D_QPU_A_STVPMD] = A | B, + [V3D_QPU_A_STVPMP] = A | B, + + [V3D_QPU_A_ITOF] = D | A, + [V3D_QPU_A_CLZ] = D | A, + [V3D_QPU_A_UTOF] = D | A, +}; + +static const uint8_t mul_op_args[] = { + [V3D_QPU_M_ADD] = D | A | B, + [V3D_QPU_M_SUB] = D | A | B, + [V3D_QPU_M_UMUL24] = D | A | B, + [V3D_QPU_M_VFMUL] = D | A | B, + [V3D_QPU_M_SMUL24] = D | A | B, + [V3D_QPU_M_MULTOP] = D | A | B, + [V3D_QPU_M_FMOV] = D | A, + [V3D_QPU_M_NOP] = 0, + [V3D_QPU_M_MOV] = D | A, + [V3D_QPU_M_FMUL] = D | A | B, +}; + +bool +v3d_qpu_add_op_has_dst(enum v3d_qpu_add_op op) +{ + assert(op < ARRAY_SIZE(add_op_args)); + + return add_op_args[op] & D; +} + +bool +v3d_qpu_mul_op_has_dst(enum v3d_qpu_mul_op op) +{ + assert(op < ARRAY_SIZE(mul_op_args)); + + return mul_op_args[op] & D; +} + +int +v3d_qpu_add_op_num_src(enum v3d_qpu_add_op op) +{ + assert(op < ARRAY_SIZE(add_op_args)); + + uint8_t args = add_op_args[op]; + if (args & B) + return 2; + else if (args & A) + return 1; + else + return 0; +} + +int +v3d_qpu_mul_op_num_src(enum v3d_qpu_mul_op op) +{ + assert(op < ARRAY_SIZE(mul_op_args)); + + uint8_t args = mul_op_args[op]; + if (args & B) + return 2; + else if (args & A) + return 1; + else + return 0; +} + +bool +v3d_qpu_magic_waddr_is_sfu(enum v3d_qpu_waddr waddr) +{ + switch (waddr) { + case V3D_QPU_WADDR_RECIP: + case V3D_QPU_WADDR_RSQRT: + case V3D_QPU_WADDR_EXP: + case V3D_QPU_WADDR_LOG: + case V3D_QPU_WADDR_SIN: + case V3D_QPU_WADDR_RSQRT2: + return true; + default: + return false; + } +} + +bool +v3d_qpu_magic_waddr_is_tmu(enum v3d_qpu_waddr waddr) +{ + switch (waddr) { + case V3D_QPU_WADDR_TMU: + case V3D_QPU_WADDR_TMUL: + case V3D_QPU_WADDR_TMUD: + case V3D_QPU_WADDR_TMUA: + case V3D_QPU_WADDR_TMUAU: + return true; + default: + return false; + } +} + +bool +v3d_qpu_magic_waddr_is_tlb(enum v3d_qpu_waddr waddr) +{ + return (waddr == V3D_QPU_WADDR_TLB || + waddr == V3D_QPU_WADDR_TLBU); +} + +bool +v3d_qpu_magic_waddr_is_vpm(enum v3d_qpu_waddr waddr) +{ + return (waddr == V3D_QPU_WADDR_VPM || + waddr == V3D_QPU_WADDR_VPMU); +} + +bool +v3d_qpu_magic_waddr_is_tsy(enum v3d_qpu_waddr waddr) +{ + return (waddr == V3D_QPU_WADDR_SYNC || + waddr == V3D_QPU_WADDR_SYNCU); +} + +bool +v3d_qpu_writes_r3(const struct v3d_qpu_instr *inst) +{ + return inst->sig.ldvary || inst->sig.ldvpm; +} + +bool +v3d_qpu_writes_r4(const struct v3d_qpu_instr *inst) +{ + if (inst->sig.ldtmu) + return true; + + if (inst->type == V3D_QPU_INSTR_TYPE_ALU) { + if (inst->alu.add.magic_write && + v3d_qpu_magic_waddr_is_sfu(inst->alu.add.waddr)) { + return true; + } + + if (inst->alu.mul.magic_write && + v3d_qpu_magic_waddr_is_sfu(inst->alu.mul.waddr)) { + return true; + } + } + + return false; +} + +bool +v3d_qpu_writes_r5(const struct v3d_qpu_instr *inst) +{ + return inst->sig.ldvary || inst->sig.ldunif; +} + +bool +v3d_qpu_uses_mux(const struct v3d_qpu_instr *inst, enum v3d_qpu_mux mux) +{ + int add_nsrc = v3d_qpu_add_op_num_src(inst->alu.add.op); + int mul_nsrc = v3d_qpu_mul_op_num_src(inst->alu.mul.op); + + return ((add_nsrc > 0 && inst->alu.add.a == mux) || + (add_nsrc > 1 && inst->alu.add.b == mux) || + (mul_nsrc > 0 && inst->alu.mul.a == mux) || + (mul_nsrc > 1 && inst->alu.mul.b == mux)); +} diff --git a/lib/mesa/src/broadcom/qpu/qpu_instr.h b/lib/mesa/src/broadcom/qpu/qpu_instr.h new file mode 100644 index 000000000..a425fae8b --- /dev/null +++ b/lib/mesa/src/broadcom/qpu/qpu_instr.h @@ -0,0 +1,411 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +/** + * @file qpu_instr.h + * + * Definitions of the unpacked form of QPU instructions. Assembly and + * disassembly will use this for talking about instructions, with qpu_encode.c + * and qpu_decode.c handling the pack and unpack of the actual 64-bit QPU + * instruction. + */ + +#ifndef QPU_INSTR_H +#define QPU_INSTR_H + +#include <stdbool.h> +#include <stdint.h> +#include "util/macros.h" + +struct v3d_device_info; + +struct v3d_qpu_sig { + bool thrsw:1; + bool ldunif:1; + bool ldtmu:1; + bool ldvary:1; + bool ldvpm:1; + bool ldtlb:1; + bool ldtlbu:1; + bool small_imm:1; + bool ucb:1; + bool rotate:1; + bool wrtmuc:1; +}; + +enum v3d_qpu_cond { + V3D_QPU_COND_NONE, + V3D_QPU_COND_IFA, + V3D_QPU_COND_IFB, + V3D_QPU_COND_IFNA, + V3D_QPU_COND_IFNB, +}; + +enum v3d_qpu_pf { + V3D_QPU_PF_NONE, + V3D_QPU_PF_PUSHZ, + V3D_QPU_PF_PUSHN, + V3D_QPU_PF_PUSHC, +}; + +enum v3d_qpu_uf { + V3D_QPU_UF_NONE, + V3D_QPU_UF_ANDZ, + V3D_QPU_UF_ANDNZ, + V3D_QPU_UF_NORNZ, + V3D_QPU_UF_NORZ, + V3D_QPU_UF_ANDN, + V3D_QPU_UF_ANDNN, + V3D_QPU_UF_NORNN, + V3D_QPU_UF_NORN, + V3D_QPU_UF_ANDC, + V3D_QPU_UF_ANDNC, + V3D_QPU_UF_NORNC, + V3D_QPU_UF_NORC, +}; + +enum v3d_qpu_waddr { + V3D_QPU_WADDR_R0 = 0, + V3D_QPU_WADDR_R1 = 1, + V3D_QPU_WADDR_R2 = 2, + V3D_QPU_WADDR_R3 = 3, + V3D_QPU_WADDR_R4 = 4, + V3D_QPU_WADDR_R5 = 5, + /* 6 is reserved, but note 3.2.2.8: "Result Writes" */ + V3D_QPU_WADDR_NOP = 6, + V3D_QPU_WADDR_TLB = 7, + V3D_QPU_WADDR_TLBU = 8, + V3D_QPU_WADDR_TMU = 9, + V3D_QPU_WADDR_TMUL = 10, + V3D_QPU_WADDR_TMUD = 11, + V3D_QPU_WADDR_TMUA = 12, + V3D_QPU_WADDR_TMUAU = 13, + V3D_QPU_WADDR_VPM = 14, + V3D_QPU_WADDR_VPMU = 15, + V3D_QPU_WADDR_SYNC = 16, + V3D_QPU_WADDR_SYNCU = 17, + /* reserved */ + V3D_QPU_WADDR_RECIP = 19, + V3D_QPU_WADDR_RSQRT = 20, + V3D_QPU_WADDR_EXP = 21, + V3D_QPU_WADDR_LOG = 22, + V3D_QPU_WADDR_SIN = 23, + V3D_QPU_WADDR_RSQRT2 = 24, +}; + +struct v3d_qpu_flags { + enum v3d_qpu_cond ac, mc; + enum v3d_qpu_pf apf, mpf; + enum v3d_qpu_uf auf, muf; +}; + +enum v3d_qpu_add_op { + V3D_QPU_A_FADD, + V3D_QPU_A_FADDNF, + V3D_QPU_A_VFPACK, + V3D_QPU_A_ADD, + V3D_QPU_A_SUB, + V3D_QPU_A_FSUB, + V3D_QPU_A_MIN, + V3D_QPU_A_MAX, + V3D_QPU_A_UMIN, + V3D_QPU_A_UMAX, + V3D_QPU_A_SHL, + V3D_QPU_A_SHR, + V3D_QPU_A_ASR, + V3D_QPU_A_ROR, + V3D_QPU_A_FMIN, + V3D_QPU_A_FMAX, + V3D_QPU_A_VFMIN, + V3D_QPU_A_AND, + V3D_QPU_A_OR, + V3D_QPU_A_XOR, + V3D_QPU_A_VADD, + V3D_QPU_A_VSUB, + V3D_QPU_A_NOT, + V3D_QPU_A_NEG, + V3D_QPU_A_FLAPUSH, + V3D_QPU_A_FLBPUSH, + V3D_QPU_A_FLBPOP, + V3D_QPU_A_SETMSF, + V3D_QPU_A_SETREVF, + V3D_QPU_A_NOP, + V3D_QPU_A_TIDX, + V3D_QPU_A_EIDX, + V3D_QPU_A_LR, + V3D_QPU_A_VFLA, + V3D_QPU_A_VFLNA, + V3D_QPU_A_VFLB, + V3D_QPU_A_VFLNB, + V3D_QPU_A_FXCD, + V3D_QPU_A_XCD, + V3D_QPU_A_FYCD, + V3D_QPU_A_YCD, + V3D_QPU_A_MSF, + V3D_QPU_A_REVF, + V3D_QPU_A_VDWWT, + V3D_QPU_A_IID, + V3D_QPU_A_SAMPID, + V3D_QPU_A_PATCHID, + V3D_QPU_A_TMUWT, + V3D_QPU_A_VPMSETUP, + V3D_QPU_A_VPMWT, + V3D_QPU_A_LDVPMV, + V3D_QPU_A_LDVPMD, + V3D_QPU_A_LDVPMP, + V3D_QPU_A_LDVPMG, + V3D_QPU_A_FCMP, + V3D_QPU_A_VFMAX, + V3D_QPU_A_FROUND, + V3D_QPU_A_FTOIN, + V3D_QPU_A_FTRUNC, + V3D_QPU_A_FTOIZ, + V3D_QPU_A_FFLOOR, + V3D_QPU_A_FTOUZ, + V3D_QPU_A_FCEIL, + V3D_QPU_A_FTOC, + V3D_QPU_A_FDX, + V3D_QPU_A_FDY, + V3D_QPU_A_STVPMV, + V3D_QPU_A_STVPMD, + V3D_QPU_A_STVPMP, + V3D_QPU_A_ITOF, + V3D_QPU_A_CLZ, + V3D_QPU_A_UTOF, +}; + +enum v3d_qpu_mul_op { + V3D_QPU_M_ADD, + V3D_QPU_M_SUB, + V3D_QPU_M_UMUL24, + V3D_QPU_M_VFMUL, + V3D_QPU_M_SMUL24, + V3D_QPU_M_MULTOP, + V3D_QPU_M_FMOV, + V3D_QPU_M_MOV, + V3D_QPU_M_NOP, + V3D_QPU_M_FMUL, +}; + +enum v3d_qpu_output_pack { + V3D_QPU_PACK_NONE, + /** + * Convert to 16-bit float, put in low 16 bits of destination leaving + * high unmodified. + */ + V3D_QPU_PACK_L, + /** + * Convert to 16-bit float, put in high 16 bits of destination leaving + * low unmodified. + */ + V3D_QPU_PACK_H, +}; + +enum v3d_qpu_input_unpack { + /** + * No-op input unpacking. Note that this enum's value doesn't match + * the packed QPU instruction value of the field (we use 0 so that the + * default on new instruction creation is no-op). + */ + V3D_QPU_UNPACK_NONE, + /** Absolute value. Only available for some operations. */ + V3D_QPU_UNPACK_ABS, + /** Convert low 16 bits from 16-bit float to 32-bit float. */ + V3D_QPU_UNPACK_L, + /** Convert high 16 bits from 16-bit float to 32-bit float. */ + V3D_QPU_UNPACK_H, + + /** Convert to 16f and replicate it to the high bits. */ + V3D_QPU_UNPACK_REPLICATE_32F_16, + + /** Replicate low 16 bits to high */ + V3D_QPU_UNPACK_REPLICATE_L_16, + + /** Replicate high 16 bits to low */ + V3D_QPU_UNPACK_REPLICATE_H_16, + + /** Swap high and low 16 bits */ + V3D_QPU_UNPACK_SWAP_16, +}; + +enum v3d_qpu_mux { + V3D_QPU_MUX_R0, + V3D_QPU_MUX_R1, + V3D_QPU_MUX_R2, + V3D_QPU_MUX_R3, + V3D_QPU_MUX_R4, + V3D_QPU_MUX_R5, + V3D_QPU_MUX_A, + V3D_QPU_MUX_B, +}; + +struct v3d_qpu_alu_instr { + struct { + enum v3d_qpu_add_op op; + enum v3d_qpu_mux a, b; + uint8_t waddr; + bool magic_write; + enum v3d_qpu_output_pack output_pack; + enum v3d_qpu_input_unpack a_unpack; + enum v3d_qpu_input_unpack b_unpack; + } add; + + struct { + enum v3d_qpu_mul_op op; + enum v3d_qpu_mux a, b; + uint8_t waddr; + bool magic_write; + enum v3d_qpu_output_pack output_pack; + enum v3d_qpu_input_unpack a_unpack; + enum v3d_qpu_input_unpack b_unpack; + } mul; +}; + +enum v3d_qpu_branch_cond { + V3D_QPU_BRANCH_COND_ALWAYS, + V3D_QPU_BRANCH_COND_A0, + V3D_QPU_BRANCH_COND_NA0, + V3D_QPU_BRANCH_COND_ALLA, + V3D_QPU_BRANCH_COND_ANYNA, + V3D_QPU_BRANCH_COND_ANYA, + V3D_QPU_BRANCH_COND_ALLNA, +}; + +enum v3d_qpu_msfign { + /** Ignore multisample flags when determining branch condition. */ + V3D_QPU_MSFIGN_NONE, + /** + * If no multisample flags are set in the lane (a pixel in the FS, a + * vertex in the VS), ignore the lane's condition when computing the + * branch condition. + */ + V3D_QPU_MSFIGN_P, + /** + * If no multisample flags are set in a 2x2 quad in the FS, ignore the + * quad's a/b conditions. + */ + V3D_QPU_MSFIGN_Q, +}; + +enum v3d_qpu_branch_dest { + V3D_QPU_BRANCH_DEST_ABS, + V3D_QPU_BRANCH_DEST_REL, + V3D_QPU_BRANCH_DEST_LINK_REG, + V3D_QPU_BRANCH_DEST_REGFILE, +}; + +struct v3d_qpu_branch_instr { + enum v3d_qpu_branch_cond cond; + enum v3d_qpu_msfign msfign; + + /** Selects how to compute the new IP if the branch is taken. */ + enum v3d_qpu_branch_dest bdi; + + /** + * Selects how to compute the new uniforms pointer if the branch is + * taken. (ABS/REL implicitly load a uniform and use that) + */ + enum v3d_qpu_branch_dest bdu; + + /** + * If set, then udest determines how the uniform stream will branch, + * otherwise the uniform stream is left as is. + */ + bool ub; + + uint8_t raddr_a; + + uint32_t offset; +}; + +enum v3d_qpu_instr_type { + V3D_QPU_INSTR_TYPE_ALU, + V3D_QPU_INSTR_TYPE_BRANCH, +}; + +struct v3d_qpu_instr { + enum v3d_qpu_instr_type type; + + struct v3d_qpu_sig sig; + uint8_t raddr_a; + uint8_t raddr_b; + struct v3d_qpu_flags flags; + + union { + struct v3d_qpu_alu_instr alu; + struct v3d_qpu_branch_instr branch; + }; +}; + +const char *v3d_qpu_magic_waddr_name(enum v3d_qpu_waddr waddr); +const char *v3d_qpu_add_op_name(enum v3d_qpu_add_op op); +const char *v3d_qpu_mul_op_name(enum v3d_qpu_mul_op op); +const char *v3d_qpu_cond_name(enum v3d_qpu_cond cond); +const char *v3d_qpu_pf_name(enum v3d_qpu_pf pf); +const char *v3d_qpu_uf_name(enum v3d_qpu_uf uf); +const char *v3d_qpu_pack_name(enum v3d_qpu_output_pack pack); +const char *v3d_qpu_unpack_name(enum v3d_qpu_input_unpack unpack); +const char *v3d_qpu_branch_cond_name(enum v3d_qpu_branch_cond cond); +const char *v3d_qpu_msfign_name(enum v3d_qpu_msfign msfign); + +bool v3d_qpu_add_op_has_dst(enum v3d_qpu_add_op op); +bool v3d_qpu_mul_op_has_dst(enum v3d_qpu_mul_op op); +int v3d_qpu_add_op_num_src(enum v3d_qpu_add_op op); +int v3d_qpu_mul_op_num_src(enum v3d_qpu_mul_op op); + +bool v3d_qpu_sig_pack(const struct v3d_device_info *devinfo, + const struct v3d_qpu_sig *sig, + uint32_t *packed_sig); +bool v3d_qpu_sig_unpack(const struct v3d_device_info *devinfo, + uint32_t packed_sig, + struct v3d_qpu_sig *sig); + +bool +v3d_qpu_flags_pack(const struct v3d_device_info *devinfo, + const struct v3d_qpu_flags *cond, + uint32_t *packed_cond); +bool +v3d_qpu_flags_unpack(const struct v3d_device_info *devinfo, + uint32_t packed_cond, + struct v3d_qpu_flags *cond); + +bool +v3d_qpu_instr_pack(const struct v3d_device_info *devinfo, + const struct v3d_qpu_instr *instr, + uint64_t *packed_instr); +bool +v3d_qpu_instr_unpack(const struct v3d_device_info *devinfo, + uint64_t packed_instr, + struct v3d_qpu_instr *instr); + +bool v3d_qpu_magic_waddr_is_sfu(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; +bool v3d_qpu_magic_waddr_is_tmu(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; +bool v3d_qpu_magic_waddr_is_tlb(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; +bool v3d_qpu_magic_waddr_is_vpm(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; +bool v3d_qpu_magic_waddr_is_tsy(enum v3d_qpu_waddr waddr) ATTRIBUTE_CONST; +bool v3d_qpu_writes_r3(const struct v3d_qpu_instr *instr) ATTRIBUTE_CONST; +bool v3d_qpu_writes_r4(const struct v3d_qpu_instr *instr) ATTRIBUTE_CONST; +bool v3d_qpu_writes_r5(const struct v3d_qpu_instr *instr) ATTRIBUTE_CONST; +bool v3d_qpu_uses_mux(const struct v3d_qpu_instr *inst, enum v3d_qpu_mux mux); + +#endif diff --git a/lib/mesa/src/broadcom/qpu/qpu_pack.c b/lib/mesa/src/broadcom/qpu/qpu_pack.c new file mode 100644 index 000000000..0ecce8666 --- /dev/null +++ b/lib/mesa/src/broadcom/qpu/qpu_pack.c @@ -0,0 +1,1206 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <string.h> +#include "util/macros.h" + +#include "broadcom/common/v3d_device_info.h" +#include "qpu_instr.h" + +#ifndef QPU_MASK +#define QPU_MASK(high, low) ((((uint64_t)1<<((high)-(low)+1))-1)<<(low)) +/* Using the GNU statement expression extension */ +#define QPU_SET_FIELD(value, field) \ + ({ \ + uint64_t fieldval = (uint64_t)(value) << field ## _SHIFT; \ + assert((fieldval & ~ field ## _MASK) == 0); \ + fieldval & field ## _MASK; \ + }) + +#define QPU_GET_FIELD(word, field) ((uint32_t)(((word) & field ## _MASK) >> field ## _SHIFT)) + +#define QPU_UPDATE_FIELD(inst, value, field) \ + (((inst) & ~(field ## _MASK)) | QPU_SET_FIELD(value, field)) +#endif /* QPU_MASK */ + +#define VC5_QPU_OP_MUL_SHIFT 58 +#define VC5_QPU_OP_MUL_MASK QPU_MASK(63, 58) + +#define VC5_QPU_SIG_SHIFT 53 +#define VC5_QPU_SIG_MASK QPU_MASK(57, 53) +# define VC5_QPU_SIG_THRSW_BIT 0x1 +# define VC5_QPU_SIG_LDUNIF_BIT 0x2 +# define VC5_QPU_SIG_LDTMU_BIT 0x4 +# define VC5_QPU_SIG_LDVARY_BIT 0x8 + +#define VC5_QPU_COND_SHIFT 46 +#define VC5_QPU_COND_MASK QPU_MASK(52, 46) + +#define VC5_QPU_COND_IFA 0 +#define VC5_QPU_COND_IFB 1 +#define VC5_QPU_COND_IFNA 2 +#define VC5_QPU_COND_IFNB 3 + +#define VC5_QPU_MM QPU_MASK(45, 45) +#define VC5_QPU_MA QPU_MASK(44, 44) + +#define V3D_QPU_WADDR_M_SHIFT 38 +#define V3D_QPU_WADDR_M_MASK QPU_MASK(43, 38) + +#define VC5_QPU_BRANCH_ADDR_LOW_SHIFT 35 +#define VC5_QPU_BRANCH_ADDR_LOW_MASK QPU_MASK(55, 35) + +#define V3D_QPU_WADDR_A_SHIFT 32 +#define V3D_QPU_WADDR_A_MASK QPU_MASK(37, 32) + +#define VC5_QPU_BRANCH_COND_SHIFT 32 +#define VC5_QPU_BRANCH_COND_MASK QPU_MASK(34, 32) + +#define VC5_QPU_BRANCH_ADDR_HIGH_SHIFT 24 +#define VC5_QPU_BRANCH_ADDR_HIGH_MASK QPU_MASK(31, 24) + +#define VC5_QPU_OP_ADD_SHIFT 24 +#define VC5_QPU_OP_ADD_MASK QPU_MASK(31, 24) + +#define VC5_QPU_MUL_B_SHIFT 21 +#define VC5_QPU_MUL_B_MASK QPU_MASK(23, 21) + +#define VC5_QPU_BRANCH_MSFIGN_SHIFT 21 +#define VC5_QPU_BRANCH_MSFIGN_MASK QPU_MASK(22, 21) + +#define VC5_QPU_MUL_A_SHIFT 18 +#define VC5_QPU_MUL_A_MASK QPU_MASK(20, 18) + +#define VC5_QPU_ADD_B_SHIFT 15 +#define VC5_QPU_ADD_B_MASK QPU_MASK(17, 15) + +#define VC5_QPU_BRANCH_BDU_SHIFT 15 +#define VC5_QPU_BRANCH_BDU_MASK QPU_MASK(17, 15) + +#define VC5_QPU_BRANCH_UB QPU_MASK(14, 14) + +#define VC5_QPU_ADD_A_SHIFT 12 +#define VC5_QPU_ADD_A_MASK QPU_MASK(14, 12) + +#define VC5_QPU_BRANCH_BDI_SHIFT 12 +#define VC5_QPU_BRANCH_BDI_MASK QPU_MASK(13, 12) + +#define VC5_QPU_RADDR_A_SHIFT 6 +#define VC5_QPU_RADDR_A_MASK QPU_MASK(11, 6) + +#define VC5_QPU_RADDR_B_SHIFT 0 +#define VC5_QPU_RADDR_B_MASK QPU_MASK(5, 0) + +#define THRSW .thrsw = true +#define LDUNIF .ldunif = true +#define LDTMU .ldtmu = true +#define LDVARY .ldvary = true +#define LDVPM .ldvpm = true +#define SMIMM .small_imm = true +#define LDTLB .ldtlb = true +#define LDTLBU .ldtlbu = true +#define UCB .ucb = true +#define ROT .rotate = true +#define WRTMUC .wrtmuc = true + +static const struct v3d_qpu_sig v33_sig_map[] = { + /* MISC R3 R4 R5 */ + [0] = { }, + [1] = { THRSW, }, + [2] = { LDUNIF }, + [3] = { THRSW, LDUNIF }, + [4] = { LDTMU, }, + [5] = { THRSW, LDTMU, }, + [6] = { LDTMU, LDUNIF }, + [7] = { THRSW, LDTMU, LDUNIF }, + [8] = { LDVARY, }, + [9] = { THRSW, LDVARY, }, + [10] = { LDVARY, LDUNIF }, + [11] = { THRSW, LDVARY, LDUNIF }, + [12] = { LDVARY, LDTMU, }, + [13] = { THRSW, LDVARY, LDTMU, }, + [14] = { SMIMM, LDVARY, }, + [15] = { SMIMM, }, + [16] = { LDTLB, }, + [17] = { LDTLBU, }, + /* 18-21 reserved */ + [22] = { UCB, }, + [23] = { ROT, }, + [24] = { LDVPM, }, + [25] = { THRSW, LDVPM, }, + [26] = { LDVPM, LDUNIF }, + [27] = { THRSW, LDVPM, LDUNIF }, + [28] = { LDVPM, LDTMU, }, + [29] = { THRSW, LDVPM, LDTMU, }, + [30] = { SMIMM, LDVPM, }, + [31] = { SMIMM, }, +}; + +bool +v3d_qpu_sig_unpack(const struct v3d_device_info *devinfo, + uint32_t packed_sig, + struct v3d_qpu_sig *sig) +{ + if (packed_sig >= ARRAY_SIZE(v33_sig_map)) + return false; + + *sig = v33_sig_map[packed_sig]; + + /* Signals with zeroed unpacked contents after element 0 are reserved. */ + return (packed_sig == 0 || + memcmp(sig, &v33_sig_map[0], sizeof(*sig) != 0)); +} + +bool +v3d_qpu_sig_pack(const struct v3d_device_info *devinfo, + const struct v3d_qpu_sig *sig, + uint32_t *packed_sig) +{ + static const struct v3d_qpu_sig *map; + + map = v33_sig_map; + + for (int i = 0; i < ARRAY_SIZE(v33_sig_map); i++) { + if (memcmp(&map[i], sig, sizeof(*sig)) == 0) { + *packed_sig = i; + return true; + } + } + + return false; +} + +bool +v3d_qpu_flags_unpack(const struct v3d_device_info *devinfo, + uint32_t packed_cond, + struct v3d_qpu_flags *cond) +{ + static const enum v3d_qpu_cond cond_map[4] = { + [0] = V3D_QPU_COND_IFA, + [1] = V3D_QPU_COND_IFB, + [2] = V3D_QPU_COND_IFNA, + [3] = V3D_QPU_COND_IFNB, + }; + + cond->ac = V3D_QPU_COND_NONE; + cond->mc = V3D_QPU_COND_NONE; + cond->apf = V3D_QPU_PF_NONE; + cond->mpf = V3D_QPU_PF_NONE; + cond->auf = V3D_QPU_UF_NONE; + cond->muf = V3D_QPU_UF_NONE; + + if (packed_cond == 0) { + return true; + } else if (packed_cond >> 2 == 0) { + cond->apf = packed_cond & 0x3; + } else if (packed_cond >> 4 == 0) { + cond->auf = (packed_cond & 0xf) - 4 + V3D_QPU_UF_ANDZ; + } else if (packed_cond == 0x10) { + return false; + } else if (packed_cond >> 2 == 0x4) { + cond->mpf = packed_cond & 0x3; + } else if (packed_cond >> 4 == 0x1) { + cond->muf = (packed_cond & 0xf) - 4 + V3D_QPU_UF_ANDZ; + } else if (packed_cond >> 4 == 0x2) { + cond->ac = ((packed_cond >> 2) & 0x3) + V3D_QPU_COND_IFA; + cond->mpf = packed_cond & 0x3; + } else if (packed_cond >> 4 == 0x3) { + cond->mc = ((packed_cond >> 2) & 0x3) + V3D_QPU_COND_IFA; + cond->apf = packed_cond & 0x3; + } else if (packed_cond >> 6) { + cond->mc = cond_map[(packed_cond >> 4) & 0x3]; + if (((packed_cond >> 2) & 0x3) == 0) { + cond->ac = cond_map[packed_cond & 0x3]; + } else { + cond->auf = (packed_cond & 0xf) - 4 + V3D_QPU_UF_ANDZ; + } + } + + return true; +} + +bool +v3d_qpu_flags_pack(const struct v3d_device_info *devinfo, + const struct v3d_qpu_flags *cond, + uint32_t *packed_cond) +{ +#define AC (1 << 0) +#define MC (1 << 1) +#define APF (1 << 2) +#define MPF (1 << 3) +#define AUF (1 << 4) +#define MUF (1 << 5) + static const struct { + uint8_t flags_present; + uint8_t bits; + } flags_table[] = { + { 0, 0 }, + { APF, 0 }, + { AUF, 0 }, + { MPF, (1 << 4) }, + { MUF, (1 << 4) }, + { AC, (1 << 5) }, + { AC | MPF, (1 << 5) }, + { MC, (1 << 5) | (1 << 4) }, + { MC | APF, (1 << 5) | (1 << 4) }, + { MC | AC, (1 << 6) }, + { MC | AUF, (1 << 6) }, + }; + + uint8_t flags_present = 0; + if (cond->ac != V3D_QPU_COND_NONE) + flags_present |= AC; + if (cond->mc != V3D_QPU_COND_NONE) + flags_present |= MC; + if (cond->apf != V3D_QPU_PF_NONE) + flags_present |= APF; + if (cond->mpf != V3D_QPU_PF_NONE) + flags_present |= MPF; + if (cond->auf != V3D_QPU_UF_NONE) + flags_present |= AUF; + if (cond->muf != V3D_QPU_UF_NONE) + flags_present |= MUF; + + for (int i = 0; i < ARRAY_SIZE(flags_table); i++) { + if (flags_table[i].flags_present != flags_present) + continue; + + *packed_cond = flags_table[i].bits; + + *packed_cond |= cond->apf; + *packed_cond |= cond->mpf; + + if (flags_present & AUF) + *packed_cond |= cond->auf - V3D_QPU_UF_ANDZ + 4; + if (flags_present & MUF) + *packed_cond |= cond->muf - V3D_QPU_UF_ANDZ + 4; + + if (flags_present & AC) + *packed_cond |= (cond->ac - V3D_QPU_COND_IFA) << 2; + + if (flags_present & MC) { + if (*packed_cond & (1 << 6)) + *packed_cond |= (cond->mc - + V3D_QPU_COND_IFA) << 4; + else + *packed_cond |= (cond->mc - + V3D_QPU_COND_IFA) << 2; + } + + return true; + } + + return false; +} + +/* Make a mapping of the table of opcodes in the spec. The opcode is + * determined by a combination of the opcode field, and in the case of 0 or + * 1-arg opcodes, the mux_b field as well. + */ +#define MUX_MASK(bot, top) (((1 << (top + 1)) - 1) - ((1 << (bot)) - 1)) +#define ANYMUX MUX_MASK(0, 7) + +struct opcode_desc { + uint8_t opcode_first; + uint8_t opcode_last; + uint8_t mux_b_mask; + uint8_t mux_a_mask; + uint8_t op; + /* 0 if it's the same across V3D versions, or a specific V3D version. */ + uint8_t ver; +}; + +static const struct opcode_desc add_ops[] = { + /* FADD is FADDNF depending on the order of the mux_a/mux_b. */ + { 0, 47, ANYMUX, ANYMUX, V3D_QPU_A_FADD }, + { 0, 47, ANYMUX, ANYMUX, V3D_QPU_A_FADDNF }, + { 53, 55, ANYMUX, ANYMUX, V3D_QPU_A_VFPACK }, + { 56, 56, ANYMUX, ANYMUX, V3D_QPU_A_ADD }, + { 57, 59, ANYMUX, ANYMUX, V3D_QPU_A_VFPACK }, + { 60, 60, ANYMUX, ANYMUX, V3D_QPU_A_SUB }, + { 61, 63, ANYMUX, ANYMUX, V3D_QPU_A_VFPACK }, + { 64, 111, ANYMUX, ANYMUX, V3D_QPU_A_FSUB }, + { 120, 120, ANYMUX, ANYMUX, V3D_QPU_A_MIN }, + { 121, 121, ANYMUX, ANYMUX, V3D_QPU_A_MAX }, + { 122, 122, ANYMUX, ANYMUX, V3D_QPU_A_UMIN }, + { 123, 123, ANYMUX, ANYMUX, V3D_QPU_A_UMAX }, + { 124, 124, ANYMUX, ANYMUX, V3D_QPU_A_SHL }, + { 125, 125, ANYMUX, ANYMUX, V3D_QPU_A_SHR }, + { 126, 126, ANYMUX, ANYMUX, V3D_QPU_A_ASR }, + { 127, 127, ANYMUX, ANYMUX, V3D_QPU_A_ROR }, + /* FMIN is instead FMAX depending on the order of the mux_a/mux_b. */ + { 128, 175, ANYMUX, ANYMUX, V3D_QPU_A_FMIN }, + { 128, 175, ANYMUX, ANYMUX, V3D_QPU_A_FMAX }, + { 176, 180, ANYMUX, ANYMUX, V3D_QPU_A_VFMIN }, + + { 181, 181, ANYMUX, ANYMUX, V3D_QPU_A_AND }, + { 182, 182, ANYMUX, ANYMUX, V3D_QPU_A_OR }, + { 183, 183, ANYMUX, ANYMUX, V3D_QPU_A_XOR }, + + { 184, 184, ANYMUX, ANYMUX, V3D_QPU_A_VADD }, + { 185, 185, ANYMUX, ANYMUX, V3D_QPU_A_VSUB }, + { 186, 186, 1 << 0, ANYMUX, V3D_QPU_A_NOT }, + { 186, 186, 1 << 1, ANYMUX, V3D_QPU_A_NEG }, + { 186, 186, 1 << 2, ANYMUX, V3D_QPU_A_FLAPUSH }, + { 186, 186, 1 << 3, ANYMUX, V3D_QPU_A_FLBPUSH }, + { 186, 186, 1 << 4, ANYMUX, V3D_QPU_A_FLBPOP }, + { 186, 186, 1 << 6, ANYMUX, V3D_QPU_A_SETMSF }, + { 186, 186, 1 << 7, ANYMUX, V3D_QPU_A_SETREVF }, + { 187, 187, 1 << 0, 1 << 0, V3D_QPU_A_NOP, 0 }, + { 187, 187, 1 << 0, 1 << 1, V3D_QPU_A_TIDX }, + { 187, 187, 1 << 0, 1 << 2, V3D_QPU_A_EIDX }, + { 187, 187, 1 << 0, 1 << 3, V3D_QPU_A_LR }, + { 187, 187, 1 << 0, 1 << 4, V3D_QPU_A_VFLA }, + { 187, 187, 1 << 0, 1 << 5, V3D_QPU_A_VFLNA }, + { 187, 187, 1 << 0, 1 << 6, V3D_QPU_A_VFLB }, + { 187, 187, 1 << 0, 1 << 7, V3D_QPU_A_VFLNB }, + + { 187, 187, 1 << 1, MUX_MASK(0, 2), V3D_QPU_A_FXCD }, + { 187, 187, 1 << 1, 1 << 3, V3D_QPU_A_XCD }, + { 187, 187, 1 << 1, MUX_MASK(4, 6), V3D_QPU_A_FYCD }, + { 187, 187, 1 << 1, 1 << 7, V3D_QPU_A_YCD }, + + { 187, 187, 1 << 2, 1 << 0, V3D_QPU_A_MSF }, + { 187, 187, 1 << 2, 1 << 1, V3D_QPU_A_REVF }, + { 187, 187, 1 << 2, 1 << 2, V3D_QPU_A_VDWWT }, + { 187, 187, 1 << 2, 1 << 5, V3D_QPU_A_TMUWT }, + { 187, 187, 1 << 2, 1 << 6, V3D_QPU_A_VPMWT }, + + { 187, 187, 1 << 3, ANYMUX, V3D_QPU_A_VPMSETUP }, + + /* FIXME: MORE COMPLICATED */ + /* { 190, 191, ANYMUX, ANYMUX, V3D_QPU_A_VFMOVABSNEGNAB }, */ + + { 192, 239, ANYMUX, ANYMUX, V3D_QPU_A_FCMP }, + { 240, 244, ANYMUX, ANYMUX, V3D_QPU_A_VFMAX }, + + { 245, 245, MUX_MASK(0, 2), ANYMUX, V3D_QPU_A_FROUND }, + { 245, 245, 1 << 3, ANYMUX, V3D_QPU_A_FTOIN }, + { 245, 245, MUX_MASK(4, 6), ANYMUX, V3D_QPU_A_FTRUNC }, + { 245, 245, 1 << 7, ANYMUX, V3D_QPU_A_FTOIZ }, + { 246, 246, MUX_MASK(0, 2), ANYMUX, V3D_QPU_A_FFLOOR }, + { 246, 246, 1 << 3, ANYMUX, V3D_QPU_A_FTOUZ }, + { 246, 246, MUX_MASK(4, 6), ANYMUX, V3D_QPU_A_FCEIL }, + { 246, 246, 1 << 7, ANYMUX, V3D_QPU_A_FTOC }, + + { 247, 247, MUX_MASK(0, 2), ANYMUX, V3D_QPU_A_FDX }, + { 247, 247, MUX_MASK(4, 6), ANYMUX, V3D_QPU_A_FDY }, + + /* The stvpms are distinguished by the waddr field. */ + { 248, 248, ANYMUX, ANYMUX, V3D_QPU_A_STVPMV }, + { 248, 248, ANYMUX, ANYMUX, V3D_QPU_A_STVPMD }, + { 248, 248, ANYMUX, ANYMUX, V3D_QPU_A_STVPMP }, + + { 252, 252, MUX_MASK(0, 2), ANYMUX, V3D_QPU_A_ITOF }, + { 252, 252, 1 << 3, ANYMUX, V3D_QPU_A_CLZ }, + { 252, 252, MUX_MASK(4, 6), ANYMUX, V3D_QPU_A_UTOF }, +}; + +static const struct opcode_desc mul_ops[] = { + { 1, 1, ANYMUX, ANYMUX, V3D_QPU_M_ADD }, + { 2, 2, ANYMUX, ANYMUX, V3D_QPU_M_SUB }, + { 3, 3, ANYMUX, ANYMUX, V3D_QPU_M_UMUL24 }, + { 4, 8, ANYMUX, ANYMUX, V3D_QPU_M_VFMUL }, + { 9, 9, ANYMUX, ANYMUX, V3D_QPU_M_SMUL24 }, + { 10, 10, ANYMUX, ANYMUX, V3D_QPU_M_MULTOP }, + { 14, 14, ANYMUX, ANYMUX, V3D_QPU_M_FMOV }, + { 15, 15, MUX_MASK(0, 3), ANYMUX, V3D_QPU_M_FMOV }, + { 15, 15, 1 << 4, 1 << 0, V3D_QPU_M_NOP, 0 }, + { 15, 15, 1 << 7, ANYMUX, V3D_QPU_M_MOV }, + { 16, 63, ANYMUX, ANYMUX, V3D_QPU_M_FMUL }, +}; + +static const struct opcode_desc * +lookup_opcode(const struct opcode_desc *opcodes, size_t num_opcodes, + uint32_t opcode, uint32_t mux_a, uint32_t mux_b) +{ + for (int i = 0; i < num_opcodes; i++) { + const struct opcode_desc *op_desc = &opcodes[i]; + + if (opcode < op_desc->opcode_first || + opcode > op_desc->opcode_last) + continue; + + if (!(op_desc->mux_b_mask & (1 << mux_b))) + continue; + + if (!(op_desc->mux_a_mask & (1 << mux_a))) + continue; + + return op_desc; + } + + return NULL; +} + +static bool +v3d_qpu_float32_unpack_unpack(uint32_t packed, + enum v3d_qpu_input_unpack *unpacked) +{ + switch (packed) { + case 0: + *unpacked = V3D_QPU_UNPACK_ABS; + return true; + case 1: + *unpacked = V3D_QPU_UNPACK_NONE; + return true; + case 2: + *unpacked = V3D_QPU_UNPACK_L; + return true; + case 3: + *unpacked = V3D_QPU_UNPACK_H; + return true; + default: + return false; + } +} + +static bool +v3d_qpu_float32_unpack_pack(enum v3d_qpu_input_unpack unpacked, + uint32_t *packed) +{ + switch (unpacked) { + case V3D_QPU_UNPACK_ABS: + *packed = 0; + return true; + case V3D_QPU_UNPACK_NONE: + *packed = 1; + return true; + case V3D_QPU_UNPACK_L: + *packed = 2; + return true; + case V3D_QPU_UNPACK_H: + *packed = 3; + return true; + default: + return false; + } +} + +static bool +v3d_qpu_float16_unpack_unpack(uint32_t packed, + enum v3d_qpu_input_unpack *unpacked) +{ + switch (packed) { + case 0: + *unpacked = V3D_QPU_UNPACK_NONE; + return true; + case 1: + *unpacked = V3D_QPU_UNPACK_REPLICATE_32F_16; + return true; + case 2: + *unpacked = V3D_QPU_UNPACK_REPLICATE_L_16; + return true; + case 3: + *unpacked = V3D_QPU_UNPACK_REPLICATE_H_16; + return true; + case 4: + *unpacked = V3D_QPU_UNPACK_SWAP_16; + return true; + default: + return false; + } +} + +static bool +v3d_qpu_float16_unpack_pack(enum v3d_qpu_input_unpack unpacked, + uint32_t *packed) +{ + switch (unpacked) { + case V3D_QPU_UNPACK_NONE: + *packed = 0; + return true; + case V3D_QPU_UNPACK_REPLICATE_32F_16: + *packed = 1; + return true; + case V3D_QPU_UNPACK_REPLICATE_L_16: + *packed = 2; + return true; + case V3D_QPU_UNPACK_REPLICATE_H_16: + *packed = 3; + return true; + case V3D_QPU_UNPACK_SWAP_16: + *packed = 4; + return true; + default: + return false; + } +} + +static bool +v3d_qpu_float32_pack_pack(enum v3d_qpu_input_unpack unpacked, + uint32_t *packed) +{ + switch (unpacked) { + case V3D_QPU_PACK_NONE: + *packed = 0; + return true; + case V3D_QPU_PACK_L: + *packed = 1; + return true; + case V3D_QPU_PACK_H: + *packed = 2; + return true; + default: + return false; + } +} + +static bool +v3d_qpu_add_unpack(const struct v3d_device_info *devinfo, uint64_t packed_inst, + struct v3d_qpu_instr *instr) +{ + uint32_t op = QPU_GET_FIELD(packed_inst, VC5_QPU_OP_ADD); + uint32_t mux_a = QPU_GET_FIELD(packed_inst, VC5_QPU_ADD_A); + uint32_t mux_b = QPU_GET_FIELD(packed_inst, VC5_QPU_ADD_B); + uint32_t waddr = QPU_GET_FIELD(packed_inst, V3D_QPU_WADDR_A); + + uint32_t map_op = op; + /* Some big clusters of opcodes are replicated with unpack + * flags + */ + if (map_op >= 249 && map_op <= 251) + map_op = (map_op - 249 + 245); + if (map_op >= 253 && map_op <= 255) + map_op = (map_op - 253 + 245); + + const struct opcode_desc *desc = + lookup_opcode(add_ops, ARRAY_SIZE(add_ops), + map_op, mux_a, mux_b); + if (!desc) + return false; + + instr->alu.add.op = desc->op; + + /* FADD/FADDNF and FMIN/FMAX are determined by the orders of the + * operands. + */ + if (((op >> 2) & 3) * 8 + mux_a > (op & 3) * 8 + mux_b) { + if (instr->alu.add.op == V3D_QPU_A_FMIN) + instr->alu.add.op = V3D_QPU_A_FMAX; + if (instr->alu.add.op == V3D_QPU_A_FADD) + instr->alu.add.op = V3D_QPU_A_FADDNF; + } + + /* Some QPU ops require a bit more than just basic opcode and mux a/b + * comparisons to distinguish them. + */ + switch (instr->alu.add.op) { + case V3D_QPU_A_STVPMV: + case V3D_QPU_A_STVPMD: + case V3D_QPU_A_STVPMP: + switch (waddr) { + case 0: + instr->alu.add.op = V3D_QPU_A_STVPMV; + break; + case 1: + instr->alu.add.op = V3D_QPU_A_STVPMD; + break; + case 2: + instr->alu.add.op = V3D_QPU_A_STVPMP; + break; + default: + return false; + } + break; + default: + break; + } + + switch (instr->alu.add.op) { + case V3D_QPU_A_FADD: + case V3D_QPU_A_FADDNF: + case V3D_QPU_A_FSUB: + case V3D_QPU_A_FMIN: + case V3D_QPU_A_FMAX: + case V3D_QPU_A_FCMP: + instr->alu.add.output_pack = (op >> 4) & 0x3; + + if (!v3d_qpu_float32_unpack_unpack((op >> 2) & 0x3, + &instr->alu.add.a_unpack)) { + return false; + } + + if (!v3d_qpu_float32_unpack_unpack((op >> 0) & 0x3, + &instr->alu.add.b_unpack)) { + return false; + } + break; + + case V3D_QPU_A_FFLOOR: + case V3D_QPU_A_FROUND: + case V3D_QPU_A_FTRUNC: + case V3D_QPU_A_FCEIL: + case V3D_QPU_A_FDX: + case V3D_QPU_A_FDY: + instr->alu.add.output_pack = mux_b & 0x3; + + if (!v3d_qpu_float32_unpack_unpack((op >> 2) & 0x3, + &instr->alu.add.a_unpack)) { + return false; + } + break; + + case V3D_QPU_A_FTOIN: + case V3D_QPU_A_FTOIZ: + case V3D_QPU_A_FTOUZ: + case V3D_QPU_A_FTOC: + instr->alu.add.output_pack = V3D_QPU_PACK_NONE; + + if (!v3d_qpu_float32_unpack_unpack((op >> 2) & 0x3, + &instr->alu.add.a_unpack)) { + return false; + } + break; + + case V3D_QPU_A_VFMIN: + case V3D_QPU_A_VFMAX: + if (!v3d_qpu_float16_unpack_unpack(op & 0x7, + &instr->alu.add.a_unpack)) { + return false; + } + + instr->alu.add.output_pack = V3D_QPU_PACK_NONE; + instr->alu.add.b_unpack = V3D_QPU_UNPACK_NONE; + break; + + default: + instr->alu.add.output_pack = V3D_QPU_PACK_NONE; + instr->alu.add.a_unpack = V3D_QPU_UNPACK_NONE; + instr->alu.add.b_unpack = V3D_QPU_UNPACK_NONE; + break; + } + + instr->alu.add.a = mux_a; + instr->alu.add.b = mux_b; + instr->alu.add.waddr = QPU_GET_FIELD(packed_inst, V3D_QPU_WADDR_A); + instr->alu.add.magic_write = packed_inst & VC5_QPU_MA; + + return true; +} + +static bool +v3d_qpu_mul_unpack(const struct v3d_device_info *devinfo, uint64_t packed_inst, + struct v3d_qpu_instr *instr) +{ + uint32_t op = QPU_GET_FIELD(packed_inst, VC5_QPU_OP_MUL); + uint32_t mux_a = QPU_GET_FIELD(packed_inst, VC5_QPU_MUL_A); + uint32_t mux_b = QPU_GET_FIELD(packed_inst, VC5_QPU_MUL_B); + + { + const struct opcode_desc *desc = + lookup_opcode(mul_ops, ARRAY_SIZE(mul_ops), + op, mux_a, mux_b); + if (!desc) + return false; + + instr->alu.mul.op = desc->op; + } + + switch (instr->alu.mul.op) { + case V3D_QPU_M_FMUL: + instr->alu.mul.output_pack = ((op >> 4) & 0x3) - 1; + + if (!v3d_qpu_float32_unpack_unpack((op >> 2) & 0x3, + &instr->alu.mul.a_unpack)) { + return false; + } + + if (!v3d_qpu_float32_unpack_unpack((op >> 0) & 0x3, + &instr->alu.mul.b_unpack)) { + return false; + } + + break; + + case V3D_QPU_M_FMOV: + instr->alu.mul.output_pack = (((op & 1) << 1) + + ((mux_b >> 2) & 1)); + + if (!v3d_qpu_float32_unpack_unpack(mux_b & 0x3, + &instr->alu.mul.a_unpack)) { + return false; + } + + break; + default: + instr->alu.mul.output_pack = V3D_QPU_PACK_NONE; + instr->alu.mul.a_unpack = V3D_QPU_UNPACK_NONE; + instr->alu.mul.b_unpack = V3D_QPU_UNPACK_NONE; + break; + } + + instr->alu.mul.a = mux_a; + instr->alu.mul.b = mux_b; + instr->alu.mul.waddr = QPU_GET_FIELD(packed_inst, V3D_QPU_WADDR_M); + instr->alu.mul.magic_write = packed_inst & VC5_QPU_MM; + + return true; +} + +static bool +v3d_qpu_add_pack(const struct v3d_device_info *devinfo, + const struct v3d_qpu_instr *instr, uint64_t *packed_instr) +{ + uint32_t waddr = instr->alu.add.waddr; + uint32_t mux_a = instr->alu.add.a; + uint32_t mux_b = instr->alu.add.b; + int nsrc = v3d_qpu_add_op_num_src(instr->alu.add.op); + const struct opcode_desc *desc; + + int opcode; + for (desc = add_ops; desc != &add_ops[ARRAY_SIZE(add_ops)]; + desc++) { + if (desc->op == instr->alu.add.op) + break; + } + if (desc == &add_ops[ARRAY_SIZE(add_ops)]) + return false; + + opcode = desc->opcode_first; + + /* If an operation doesn't use an arg, its mux values may be used to + * identify the operation type. + */ + if (nsrc < 2) + mux_b = ffs(desc->mux_b_mask) - 1; + + if (nsrc < 1) + mux_a = ffs(desc->mux_a_mask) - 1; + + switch (instr->alu.add.op) { + case V3D_QPU_A_STVPMV: + waddr = 0; + break; + case V3D_QPU_A_STVPMD: + waddr = 1; + break; + case V3D_QPU_A_STVPMP: + waddr = 2; + break; + default: + break; + } + + switch (instr->alu.add.op) { + case V3D_QPU_A_FADD: + case V3D_QPU_A_FADDNF: + case V3D_QPU_A_FSUB: + case V3D_QPU_A_FMIN: + case V3D_QPU_A_FMAX: + case V3D_QPU_A_FCMP: { + uint32_t output_pack; + uint32_t a_unpack; + uint32_t b_unpack; + + if (!v3d_qpu_float32_pack_pack(instr->alu.add.output_pack, + &output_pack)) { + return false; + } + opcode |= output_pack << 4; + + if (!v3d_qpu_float32_unpack_pack(instr->alu.add.a_unpack, + &a_unpack)) { + return false; + } + + if (!v3d_qpu_float32_unpack_pack(instr->alu.add.b_unpack, + &b_unpack)) { + return false; + } + + /* These operations with commutative operands are + * distinguished by which order their operands come in. + */ + bool ordering = a_unpack * 8 + mux_a > b_unpack * 8 + mux_b; + if (((instr->alu.add.op == V3D_QPU_A_FMIN || + instr->alu.add.op == V3D_QPU_A_FADD) && ordering) || + ((instr->alu.add.op == V3D_QPU_A_FMAX || + instr->alu.add.op == V3D_QPU_A_FADDNF) && !ordering)) { + uint32_t temp; + + temp = a_unpack; + a_unpack = b_unpack; + b_unpack = temp; + + temp = mux_a; + mux_a = mux_b; + mux_b = temp; + } + + opcode |= a_unpack << 2; + opcode |= b_unpack << 0; + break; + } + + case V3D_QPU_A_FFLOOR: + case V3D_QPU_A_FROUND: + case V3D_QPU_A_FTRUNC: + case V3D_QPU_A_FCEIL: + case V3D_QPU_A_FDX: + case V3D_QPU_A_FDY: { + uint32_t packed; + + if (!v3d_qpu_float32_pack_pack(instr->alu.add.output_pack, + &packed)) { + return false; + } + mux_b |= packed; + + if (!v3d_qpu_float32_unpack_pack(instr->alu.add.a_unpack, + &packed)) { + return false; + } + if (packed == 0) + return false; + opcode |= packed << 2; + break; + } + + case V3D_QPU_A_FTOIN: + case V3D_QPU_A_FTOIZ: + case V3D_QPU_A_FTOUZ: + case V3D_QPU_A_FTOC: + if (instr->alu.add.output_pack != V3D_QPU_PACK_NONE) + return false; + + uint32_t packed; + if (!v3d_qpu_float32_unpack_pack(instr->alu.add.a_unpack, + &packed)) { + return false; + } + if (packed == 0) + return false; + opcode |= packed << 2; + + break; + + case V3D_QPU_A_VFMIN: + case V3D_QPU_A_VFMAX: + if (instr->alu.add.output_pack != V3D_QPU_PACK_NONE || + instr->alu.add.b_unpack != V3D_QPU_UNPACK_NONE) { + return false; + } + + if (!v3d_qpu_float16_unpack_pack(instr->alu.add.a_unpack, + &packed)) { + return false; + } + opcode |= packed; + break; + + default: + if (instr->alu.add.op != V3D_QPU_A_NOP && + (instr->alu.add.output_pack != V3D_QPU_PACK_NONE || + instr->alu.add.a_unpack != V3D_QPU_UNPACK_NONE || + instr->alu.add.b_unpack != V3D_QPU_UNPACK_NONE)) { + return false; + } + break; + } + + *packed_instr |= QPU_SET_FIELD(mux_a, VC5_QPU_ADD_A); + *packed_instr |= QPU_SET_FIELD(mux_b, VC5_QPU_ADD_B); + *packed_instr |= QPU_SET_FIELD(opcode, VC5_QPU_OP_ADD); + *packed_instr |= QPU_SET_FIELD(waddr, V3D_QPU_WADDR_A); + if (instr->alu.add.magic_write) + *packed_instr |= VC5_QPU_MA; + + return true; +} + +static bool +v3d_qpu_mul_pack(const struct v3d_device_info *devinfo, + const struct v3d_qpu_instr *instr, uint64_t *packed_instr) +{ + uint32_t mux_a = instr->alu.mul.a; + uint32_t mux_b = instr->alu.mul.b; + int nsrc = v3d_qpu_mul_op_num_src(instr->alu.mul.op); + const struct opcode_desc *desc; + + for (desc = mul_ops; desc != &mul_ops[ARRAY_SIZE(mul_ops)]; + desc++) { + if (desc->op == instr->alu.mul.op) + break; + } + if (desc == &mul_ops[ARRAY_SIZE(mul_ops)]) + return false; + + uint32_t opcode = desc->opcode_first; + + /* Some opcodes have a single valid value for their mux a/b, so set + * that here. If mux a/b determine packing, it will be set below. + */ + if (nsrc < 2) + mux_b = ffs(desc->mux_b_mask) - 1; + + if (nsrc < 1) + mux_a = ffs(desc->mux_a_mask) - 1; + + switch (instr->alu.mul.op) { + case V3D_QPU_M_FMUL: { + uint32_t packed; + + if (!v3d_qpu_float32_pack_pack(instr->alu.mul.output_pack, + &packed)) { + return false; + } + /* No need for a +1 because desc->opcode_first has a 1 in this + * field. + */ + opcode += packed << 4; + + if (!v3d_qpu_float32_unpack_pack(instr->alu.mul.a_unpack, + &packed)) { + return false; + } + opcode |= packed << 2; + + if (!v3d_qpu_float32_unpack_pack(instr->alu.mul.b_unpack, + &packed)) { + return false; + } + opcode |= packed << 0; + break; + } + + case V3D_QPU_M_FMOV: { + uint32_t packed; + + if (!v3d_qpu_float32_pack_pack(instr->alu.mul.output_pack, + &packed)) { + return false; + } + opcode |= (packed >> 1) & 1; + mux_b = (packed & 1) << 2; + + if (!v3d_qpu_float32_unpack_pack(instr->alu.mul.a_unpack, + &packed)) { + return false; + } + mux_b |= packed; + break; + } + + default: + break; + } + + *packed_instr |= QPU_SET_FIELD(mux_a, VC5_QPU_MUL_A); + *packed_instr |= QPU_SET_FIELD(mux_b, VC5_QPU_MUL_B); + + *packed_instr |= QPU_SET_FIELD(opcode, VC5_QPU_OP_MUL); + *packed_instr |= QPU_SET_FIELD(instr->alu.mul.waddr, V3D_QPU_WADDR_M); + if (instr->alu.mul.magic_write) + *packed_instr |= VC5_QPU_MM; + + return true; +} + +static bool +v3d_qpu_instr_unpack_alu(const struct v3d_device_info *devinfo, + uint64_t packed_instr, + struct v3d_qpu_instr *instr) +{ + instr->type = V3D_QPU_INSTR_TYPE_ALU; + + if (!v3d_qpu_sig_unpack(devinfo, + QPU_GET_FIELD(packed_instr, VC5_QPU_SIG), + &instr->sig)) + return false; + + if (!v3d_qpu_flags_unpack(devinfo, + QPU_GET_FIELD(packed_instr, VC5_QPU_COND), + &instr->flags)) + return false; + + instr->raddr_a = QPU_GET_FIELD(packed_instr, VC5_QPU_RADDR_A); + instr->raddr_b = QPU_GET_FIELD(packed_instr, VC5_QPU_RADDR_B); + + if (!v3d_qpu_add_unpack(devinfo, packed_instr, instr)) + return false; + + if (!v3d_qpu_mul_unpack(devinfo, packed_instr, instr)) + return false; + + return true; +} + +static bool +v3d_qpu_instr_unpack_branch(const struct v3d_device_info *devinfo, + uint64_t packed_instr, + struct v3d_qpu_instr *instr) +{ + instr->type = V3D_QPU_INSTR_TYPE_BRANCH; + + uint32_t cond = QPU_GET_FIELD(packed_instr, VC5_QPU_BRANCH_COND); + if (cond == 0) + instr->branch.cond = V3D_QPU_BRANCH_COND_ALWAYS; + else if (V3D_QPU_BRANCH_COND_A0 + (cond - 2) <= + V3D_QPU_BRANCH_COND_ALLNA) + instr->branch.cond = V3D_QPU_BRANCH_COND_A0 + (cond - 2); + else + return false; + + uint32_t msfign = QPU_GET_FIELD(packed_instr, VC5_QPU_BRANCH_MSFIGN); + if (msfign == 3) + return false; + instr->branch.msfign = msfign; + + instr->branch.bdi = QPU_GET_FIELD(packed_instr, VC5_QPU_BRANCH_BDI); + + instr->branch.ub = packed_instr & VC5_QPU_BRANCH_UB; + if (instr->branch.ub) { + instr->branch.bdu = QPU_GET_FIELD(packed_instr, + VC5_QPU_BRANCH_BDU); + } + + instr->branch.raddr_a = QPU_GET_FIELD(packed_instr, + VC5_QPU_RADDR_A); + + instr->branch.offset = 0; + + instr->branch.offset += + QPU_GET_FIELD(packed_instr, + VC5_QPU_BRANCH_ADDR_LOW) << 3; + + instr->branch.offset += + QPU_GET_FIELD(packed_instr, + VC5_QPU_BRANCH_ADDR_HIGH) << 24; + + return true; +} + +bool +v3d_qpu_instr_unpack(const struct v3d_device_info *devinfo, + uint64_t packed_instr, + struct v3d_qpu_instr *instr) +{ + if (QPU_GET_FIELD(packed_instr, VC5_QPU_OP_MUL) != 0) { + return v3d_qpu_instr_unpack_alu(devinfo, packed_instr, instr); + } else { + uint32_t sig = QPU_GET_FIELD(packed_instr, VC5_QPU_SIG); + + if ((sig & 24) == 16) { + return v3d_qpu_instr_unpack_branch(devinfo, packed_instr, + instr); + } else { + return false; + } + } +} + +static bool +v3d_qpu_instr_pack_alu(const struct v3d_device_info *devinfo, + const struct v3d_qpu_instr *instr, + uint64_t *packed_instr) +{ + uint32_t sig; + if (!v3d_qpu_sig_pack(devinfo, &instr->sig, &sig)) + return false; + *packed_instr |= QPU_SET_FIELD(sig, VC5_QPU_SIG); + + if (instr->type == V3D_QPU_INSTR_TYPE_ALU) { + *packed_instr |= QPU_SET_FIELD(instr->raddr_a, VC5_QPU_RADDR_A); + *packed_instr |= QPU_SET_FIELD(instr->raddr_b, VC5_QPU_RADDR_B); + + if (!v3d_qpu_add_pack(devinfo, instr, packed_instr)) + return false; + if (!v3d_qpu_mul_pack(devinfo, instr, packed_instr)) + return false; + + uint32_t flags; + if (!v3d_qpu_flags_pack(devinfo, &instr->flags, &flags)) + return false; + *packed_instr |= QPU_SET_FIELD(flags, VC5_QPU_COND); + } + + return true; +} + +static bool +v3d_qpu_instr_pack_branch(const struct v3d_device_info *devinfo, + const struct v3d_qpu_instr *instr, + uint64_t *packed_instr) +{ + *packed_instr |= QPU_SET_FIELD(16, VC5_QPU_SIG); + + if (instr->branch.cond != V3D_QPU_BRANCH_COND_ALWAYS) { + *packed_instr |= QPU_SET_FIELD(2 + (instr->branch.cond - + V3D_QPU_BRANCH_COND_A0), + VC5_QPU_BRANCH_COND); + } + + *packed_instr |= QPU_SET_FIELD(instr->branch.msfign, + VC5_QPU_BRANCH_MSFIGN); + + *packed_instr |= QPU_SET_FIELD(instr->branch.bdi, + VC5_QPU_BRANCH_BDI); + + if (instr->branch.ub) { + *packed_instr |= VC5_QPU_BRANCH_UB; + *packed_instr |= QPU_SET_FIELD(instr->branch.bdu, + VC5_QPU_BRANCH_BDU); + } + + switch (instr->branch.bdi) { + case V3D_QPU_BRANCH_DEST_ABS: + case V3D_QPU_BRANCH_DEST_REL: + *packed_instr |= QPU_SET_FIELD(instr->branch.msfign, + VC5_QPU_BRANCH_MSFIGN); + + *packed_instr |= QPU_SET_FIELD((instr->branch.offset & + ~0xff000000) >> 3, + VC5_QPU_BRANCH_ADDR_LOW); + + *packed_instr |= QPU_SET_FIELD(instr->branch.offset >> 24, + VC5_QPU_BRANCH_ADDR_HIGH); + + case V3D_QPU_BRANCH_DEST_REGFILE: + *packed_instr |= QPU_SET_FIELD(instr->branch.raddr_a, + VC5_QPU_RADDR_A); + break; + + default: + break; + } + + return true; +} + +bool +v3d_qpu_instr_pack(const struct v3d_device_info *devinfo, + const struct v3d_qpu_instr *instr, + uint64_t *packed_instr) +{ + *packed_instr = 0; + + switch (instr->type) { + case V3D_QPU_INSTR_TYPE_ALU: + return v3d_qpu_instr_pack_alu(devinfo, instr, packed_instr); + case V3D_QPU_INSTR_TYPE_BRANCH: + return v3d_qpu_instr_pack_branch(devinfo, instr, packed_instr); + default: + return false; + } +} diff --git a/lib/mesa/src/broadcom/qpu/tests/qpu_disasm.c b/lib/mesa/src/broadcom/qpu/tests/qpu_disasm.c new file mode 100644 index 000000000..c7f6476de --- /dev/null +++ b/lib/mesa/src/broadcom/qpu/tests/qpu_disasm.c @@ -0,0 +1,146 @@ +/* + * Copyright © 2016 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <string.h> +#include "util/macros.h" +#include "broadcom/common/v3d_device_info.h" +#include "broadcom/qpu/qpu_disasm.h" +#include "broadcom/qpu/qpu_instr.h" + +static const struct { + int ver; + uint64_t inst; + const char *expected; +} tests[] = { + { 33, 0x3d003186bb800000ull, "nop ; nop ; ldvary" }, + { 33, 0x3c20318105829000ull, "fadd r1, r1, r5 ; nop ; thrsw" }, + { 33, 0x3c403186bb81d000ull, "vpmsetup -, r5 ; nop ; ldunif" }, + { 33, 0x3f003186bb800000ull, "nop ; nop ; ldvpm" }, + { 33, 0x3c002380b6edb000ull, "or rf0, r3, r3 ; mov vpm, r3" }, + { 33, 0x57403006bbb80000ull, "nop ; fmul r0, rf0, r5 ; ldvpm; ldunif" }, + + /* branch conditions */ + { 33, 0x02000006002034c0ull, "b.anyap rf19" }, + { 33, 0x02679356b4201000ull, "b.anyap -1268280496" }, + { 33, 0x02b76a2dd0400000ull, "b.anynaq zero_addr+0xd0b76a28" }, + { 33, 0x0200000500402000ull, "b.anynaq lri" }, + { 33, 0x0216fe167301c8c0ull, "bu.anya zero_addr+0x7316fe10, rf35" }, + { 33, 0x020000050040e000ull, "bu.anynaq lri, r:unif" }, + { 33, 0x0200000300006000ull, "bu.na0 lri, a:unif" }, + + /* Special waddr names */ + { 33, 0x3c00318735808000ull, "vfpack tlb, r0, r1 ; nop" }, + { 33, 0xe0571c938e8d5000ull, "fmax.andc recip, r5.h, r2.l; fmul.ifb rf50.h, r3.l, r4.abs; ldunif" }, + { 33, 0xc04098d4382c9000ull, "add.pushn rsqrt, r1, r1; fmul rf35.h, r3.abs, r1.abs; ldunif" }, + { 33, 0x481edcd6b3184500ull, "vfmin.norn log, r4.hh, r0; fmul.ifnb rf51, rf20.abs, r0.l" }, + { 33, 0x041618d57c453000ull, "shl.andn exp, r3, r2; add.ifb rf35, r1, r2" }, + { 33, 0x7048e5da49272800ull, "fsub.ifa rf26, r2.l, rf32; fmul.pushc sin, r1.h, r1.abs; ldunif" }, + +}; + +static void +swap_mux(enum v3d_qpu_mux *a, enum v3d_qpu_mux *b) +{ + enum v3d_qpu_mux t = *a; + *a = *b; + *b = t; +} + +static void +swap_pack(enum v3d_qpu_input_unpack *a, enum v3d_qpu_input_unpack *b) +{ + enum v3d_qpu_input_unpack t = *a; + *a = *b; + *b = t; +} + +int +main(int argc, char **argv) +{ + struct v3d_device_info devinfo = { }; + int retval = 0; + + for (int i = 0; i < ARRAY_SIZE(tests); i++) { + devinfo.ver = tests[i].ver; + + printf("Testing v%d.%d 0x%016llx... ", + devinfo.ver / 10, devinfo.ver % 10, + (long long)tests[i].inst); + + const char *disasm_output = v3d_qpu_disasm(&devinfo, + tests[i].inst); + + if (strcmp(disasm_output, tests[i].expected) != 0) { + printf("FAIL\n"); + printf(" Expected: \"%s\"\n", tests[i].expected); + printf(" Got: \"%s\"\n", disasm_output); + retval = 1; + continue; + } + + struct v3d_qpu_instr instr; + if (!v3d_qpu_instr_unpack(&devinfo, tests[i].inst, &instr)) { + printf("FAIL (unpack) %s\n", tests[i].expected); + retval = 1; + continue; + } + + if (instr.type == V3D_QPU_INSTR_TYPE_ALU) { + switch (instr.alu.add.op) { + case V3D_QPU_A_FADD: + case V3D_QPU_A_FADDNF: + case V3D_QPU_A_FMIN: + case V3D_QPU_A_FMAX: + /* Swap the operands to be sure that we test + * how the QPUs distinguish between these ops. + */ + swap_mux(&instr.alu.add.a, + &instr.alu.add.b); + swap_pack(&instr.alu.add.a_unpack, + &instr.alu.add.b_unpack); + default: + break; + } + } + + uint64_t repack; + if (!v3d_qpu_instr_pack(&devinfo, &instr, &repack)) { + printf("FAIL (pack) %s\n", tests[i].expected); + retval = 1; + continue; + } + + if (repack != tests[i].inst) { + printf("FAIL (repack) 0x%016llx\n", (long long)repack); + printf(" Expected: \"%s\"\n", tests[i].expected); + const char *redisasm = v3d_qpu_disasm(&devinfo, repack); + printf(" Got: \"%s\"\n", redisasm); + retval = 1; + } + + printf("PASS\n"); + } + + return retval; +} diff --git a/lib/mesa/src/egl/SConscript b/lib/mesa/src/egl/SConscript index 8f8b11a61..927092d22 100644 --- a/lib/mesa/src/egl/SConscript +++ b/lib/mesa/src/egl/SConscript @@ -24,6 +24,8 @@ env.Append(CPPDEFINES = [ ]) egl_sources.append('drivers/haiku/egl_haiku.cpp') +env.Prepend(LIBS = [mesautil]) + egl = env.SharedLibrary( target = 'EGL', source = egl_sources, diff --git a/lib/mesa/src/egl/drivers/dri2/platform_x11_dri3.h b/lib/mesa/src/egl/drivers/dri2/platform_x11_dri3.h index 13d857242..96e7ee972 100644 --- a/lib/mesa/src/egl/drivers/dri2/platform_x11_dri3.h +++ b/lib/mesa/src/egl/drivers/dri2/platform_x11_dri3.h @@ -28,7 +28,7 @@ _EGL_DRIVER_TYPECAST(dri3_egl_surface, _EGLSurface, obj) struct dri3_egl_surface { - _EGLSurface base; + struct dri2_egl_surface surf; struct loader_dri3_drawable loader_drawable; }; diff --git a/lib/mesa/src/egl/main/eglcurrent.h b/lib/mesa/src/egl/main/eglcurrent.h index 9ec07bac8..d9a4a9017 100644 --- a/lib/mesa/src/egl/main/eglcurrent.h +++ b/lib/mesa/src/egl/main/eglcurrent.h @@ -99,13 +99,6 @@ _eglGetCurrentContext(void); extern EGLBoolean _eglError(EGLint errCode, const char *msg); -extern EGLLabelKHR -_eglGetThreadLabel(void); - -extern void -_eglDebugReportFull(EGLenum error, const char *command, const char *funcName, - EGLint type, EGLLabelKHR objectLabel, const char *message, ...); - extern void _eglDebugReport(EGLenum error, const char *funcName, EGLint type, const char *message, ...); diff --git a/lib/mesa/src/egl/main/egldriver.c b/lib/mesa/src/egl/main/egldriver.c index b9b21dec5..34a90ae5d 100644 --- a/lib/mesa/src/egl/main/egldriver.c +++ b/lib/mesa/src/egl/main/egldriver.c @@ -44,250 +44,48 @@ #include "egldriver.h" #include "egllog.h" -typedef struct _egl_module { - char *Name; - _EGLMain_t BuiltIn; - _EGLDriver *Driver; -} _EGLModule; +#include "util/debug.h" static mtx_t _eglModuleMutex = _MTX_INITIALIZER_NP; -static _EGLArray *_eglModules; +static _EGLDriver *_eglDriver; -const struct { - const char *name; - _EGLMain_t main; -} _eglBuiltInDrivers[] = { -#ifdef _EGL_BUILT_IN_DRIVER_DRI2 - { "egl_dri2", _eglBuiltInDriverDRI2 }, -#endif -#ifdef _EGL_BUILT_IN_DRIVER_HAIKU - { "egl_haiku", _eglBuiltInDriverHaiku }, -#endif - { NULL, NULL } -}; - -/** - * Load a module and create the driver object. - */ -static EGLBoolean -_eglLoadModule(_EGLModule *mod) -{ - _EGLDriver *drv; - - if (mod->Driver) - return EGL_TRUE; - - if (!mod->BuiltIn) - return EGL_FALSE; - - drv = mod->BuiltIn(NULL); - if (!drv || !drv->Name) - return EGL_FALSE; - - mod->Driver = drv; - - return EGL_TRUE; -} - - -/** - * Unload a module. - */ -static void -_eglUnloadModule(_EGLModule *mod) -{ - /* destroy the driver */ - if (mod->Driver && mod->Driver->Unload) - mod->Driver->Unload(mod->Driver); - - mod->Driver = NULL; -} - - -/** - * Add a module to the module array. - */ -static _EGLModule * -_eglAddModule(const char *name) -{ - _EGLModule *mod; - EGLint i; - - if (!_eglModules) { - _eglModules = _eglCreateArray("Module", 8); - if (!_eglModules) - return NULL; - } - - /* find duplicates */ - for (i = 0; i < _eglModules->Size; i++) { - mod = _eglModules->Elements[i]; - if (strcmp(mod->Name, name) == 0) - return mod; - } - - /* allocate a new one */ - mod = calloc(1, sizeof(*mod)); - if (mod) { - mod->Name = strdup(name); - if (!mod->Name) { - free(mod); - mod = NULL; - } - } - if (mod) { - _eglAppendArray(_eglModules, (void *) mod); - _eglLog(_EGL_DEBUG, "added %s to module array", mod->Name); - } - - return mod; -} - - -/** - * Free a module. - */ -static void -_eglFreeModule(void *module) -{ - _EGLModule *mod = (_EGLModule *) module; - - _eglUnloadModule(mod); - free(mod->Name); - free(mod); -} - - -/** - * Add the user driver to the module array. - * - * The user driver is specified by EGL_DRIVER. - */ -static EGLBoolean -_eglAddUserDriver(void) -{ - char *env; - - env = getenv("EGL_DRIVER"); - if (env) { - EGLint i; - - for (i = 0; _eglBuiltInDrivers[i].name; i++) { - if (!strcmp(_eglBuiltInDrivers[i].name, env)) { - _EGLModule *mod = _eglAddModule(env); - if (mod) - mod->BuiltIn = _eglBuiltInDrivers[i].main; - - return EGL_TRUE; - } - } - } - - return EGL_FALSE; -} - - -/** - * Add built-in drivers to the module array. - */ -static void -_eglAddBuiltInDrivers(void) +static _EGLDriver * +_eglGetDriver(void) { - _EGLModule *mod; - EGLint i; - - for (i = 0; _eglBuiltInDrivers[i].name; i++) { - mod = _eglAddModule(_eglBuiltInDrivers[i].name); - if (mod) - mod->BuiltIn = _eglBuiltInDrivers[i].main; - } -} + mtx_lock(&_eglModuleMutex); + if (!_eglDriver) + _eglDriver = _eglBuiltInDriver(); -/** - * Add drivers to the module array. Drivers will be loaded as they are matched - * to displays. - */ -static EGLBoolean -_eglAddDrivers(void) -{ - if (_eglModules) - return EGL_TRUE; - - if (!_eglAddUserDriver()) { - /* - * Add other drivers only when EGL_DRIVER is not set. The order here - * decides the priorities. - */ - _eglAddBuiltInDrivers(); - } + mtx_unlock(&_eglModuleMutex); - return (_eglModules != NULL); + return _eglDriver; } - -/** - * A helper function for _eglMatchDriver. It finds the first driver that can - * initialize the display and return. - */ static _EGLDriver * _eglMatchAndInitialize(_EGLDisplay *dpy) { - _EGLDriver *drv = NULL; - EGLint i = 0; - - if (!_eglAddDrivers()) { - _eglLog(_EGL_WARNING, "failed to find any driver"); - return NULL; - } - - if (dpy->Driver) { - drv = dpy->Driver; - /* no re-matching? */ - if (!drv->API.Initialize(drv, dpy)) - drv = NULL; - return drv; - } - - while (i < _eglModules->Size) { - _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i]; + if (_eglGetDriver()) + if (_eglDriver->API.Initialize(_eglDriver, dpy)) + return _eglDriver; - if (!_eglLoadModule(mod)) { - /* remove invalid modules */ - _eglEraseArray(_eglModules, i, _eglFreeModule); - continue; - } - - if (mod->Driver->API.Initialize(mod->Driver, dpy)) { - drv = mod->Driver; - break; - } - else { - i++; - } - } - - return drv; + return NULL; } - /** - * Match a display to a driver. The display is initialized unless test_only is - * true. The matching is done by finding the first driver that can initialize - * the display. + * Match a display to a driver. The matching is done by finding the first + * driver that can initialize the display. */ _EGLDriver * -_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only) +_eglMatchDriver(_EGLDisplay *dpy) { _EGLDriver *best_drv; assert(!dpy->Initialized); - mtx_lock(&_eglModuleMutex); - /* set options */ - dpy->Options.TestOnly = test_only; - dpy->Options.UseFallback = EGL_FALSE; + dpy->Options.UseFallback = + env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); best_drv = _eglMatchAndInitialize(dpy); if (!best_drv) { @@ -295,49 +93,25 @@ _eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only) best_drv = _eglMatchAndInitialize(dpy); } - mtx_unlock(&_eglModuleMutex); - if (best_drv) { - _eglLog(_EGL_DEBUG, "the best driver is %s%s", - best_drv->Name, (test_only) ? " (test only) " : ""); - if (!test_only) { - dpy->Driver = best_drv; - dpy->Initialized = EGL_TRUE; - } + _eglLog(_EGL_DEBUG, "the best driver is %s", + best_drv->Name); + dpy->Driver = best_drv; + dpy->Initialized = EGL_TRUE; } return best_drv; } - __eglMustCastToProperFunctionPointerType _eglGetDriverProc(const char *procname) { - EGLint i; - _EGLProc proc = NULL; - - if (!_eglModules) { - /* load the driver for the default display */ - EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - _EGLDisplay *dpy = _eglLookupDisplay(egldpy); - if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE)) - return NULL; - } + if (_eglGetDriver()) + return _eglDriver->API.GetProcAddress(_eglDriver, procname); - for (i = 0; i < _eglModules->Size; i++) { - _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i]; - - if (!mod->Driver) - break; - proc = mod->Driver->API.GetProcAddress(mod->Driver, procname); - if (proc) - break; - } - - return proc; + return NULL; } - /** * Unload all drivers. */ @@ -345,8 +119,6 @@ void _eglUnloadDrivers(void) { /* this is called at atexit time */ - if (_eglModules) { - _eglDestroyArray(_eglModules, _eglFreeModule); - _eglModules = NULL; - } + free(_eglDriver); + _eglDriver = NULL; } diff --git a/lib/mesa/src/egl/main/egldriver.h b/lib/mesa/src/egl/main/egldriver.h index 1cf662844..6ab667c4e 100644 --- a/lib/mesa/src/egl/main/egldriver.h +++ b/lib/mesa/src/egl/main/egldriver.h @@ -70,9 +70,6 @@ extern "C" { _EGL_DRIVER_TYPECAST(drvname ## _config, _EGLConfig, obj) -typedef _EGLDriver *(*_EGLMain_t)(const char *args); - - /** * Base class for device drivers. */ @@ -80,27 +77,16 @@ struct _egl_driver { const char *Name; /**< name of this driver */ - /** - * Release the driver resource. - * - * It is called before dlclose(). - */ - void (*Unload)(_EGLDriver *drv); - _EGLAPI API; /**< EGL API dispatch table */ }; -extern _EGLDriver * -_eglBuiltInDriverDRI2(const char *args); - - extern _EGLDriver* -_eglBuiltInDriverHaiku(const char* args); +_eglBuiltInDriver(void); extern _EGLDriver * -_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only); +_eglMatchDriver(_EGLDisplay *dpy); extern __eglMustCastToProperFunctionPointerType diff --git a/lib/mesa/src/egl/wayland/wayland-drm/Makefile.am b/lib/mesa/src/egl/wayland/wayland-drm/Makefile.am index f40ff4841..b27edddaf 100644 --- a/lib/mesa/src/egl/wayland/wayland-drm/Makefile.am +++ b/lib/mesa/src/egl/wayland/wayland-drm/Makefile.am @@ -2,7 +2,7 @@ AM_CFLAGS = -I$(top_srcdir)/src/egl/main \ -I$(top_srcdir)/include \ $(DEFINES) \ $(VISIBILITY_CFLAGS) \ - $(WAYLAND_CFLAGS) + $(WAYLAND_SERVER_CFLAGS) noinst_LTLIBRARIES = libwayland-drm.la libwayland_drm_la_SOURCES = \ diff --git a/lib/mesa/src/egl/wayland/wayland-drm/wayland-drm.h b/lib/mesa/src/egl/wayland/wayland-drm/wayland-drm.h index 7892d561f..111383ff1 100644 --- a/lib/mesa/src/egl/wayland/wayland-drm/wayland-drm.h +++ b/lib/mesa/src/egl/wayland/wayland-drm/wayland-drm.h @@ -3,71 +3,9 @@ #include <wayland-server.h> -#ifndef WL_DRM_FORMAT_ENUM -#define WL_DRM_FORMAT_ENUM -enum wl_drm_format { - WL_DRM_FORMAT_C8 = 0x20203843, - WL_DRM_FORMAT_RGB332 = 0x38424752, - WL_DRM_FORMAT_BGR233 = 0x38524742, - WL_DRM_FORMAT_XRGB4444 = 0x32315258, - WL_DRM_FORMAT_XBGR4444 = 0x32314258, - WL_DRM_FORMAT_RGBX4444 = 0x32315852, - WL_DRM_FORMAT_BGRX4444 = 0x32315842, - WL_DRM_FORMAT_ARGB4444 = 0x32315241, - WL_DRM_FORMAT_ABGR4444 = 0x32314241, - WL_DRM_FORMAT_RGBA4444 = 0x32314152, - WL_DRM_FORMAT_BGRA4444 = 0x32314142, - WL_DRM_FORMAT_XRGB1555 = 0x35315258, - WL_DRM_FORMAT_XBGR1555 = 0x35314258, - WL_DRM_FORMAT_RGBX5551 = 0x35315852, - WL_DRM_FORMAT_BGRX5551 = 0x35315842, - WL_DRM_FORMAT_ARGB1555 = 0x35315241, - WL_DRM_FORMAT_ABGR1555 = 0x35314241, - WL_DRM_FORMAT_RGBA5551 = 0x35314152, - WL_DRM_FORMAT_BGRA5551 = 0x35314142, - WL_DRM_FORMAT_RGB565 = 0x36314752, - WL_DRM_FORMAT_BGR565 = 0x36314742, - WL_DRM_FORMAT_RGB888 = 0x34324752, - WL_DRM_FORMAT_BGR888 = 0x34324742, - WL_DRM_FORMAT_XRGB8888 = 0x34325258, - WL_DRM_FORMAT_XBGR8888 = 0x34324258, - WL_DRM_FORMAT_RGBX8888 = 0x34325852, - WL_DRM_FORMAT_BGRX8888 = 0x34325842, - WL_DRM_FORMAT_ARGB8888 = 0x34325241, - WL_DRM_FORMAT_ABGR8888 = 0x34324241, - WL_DRM_FORMAT_RGBA8888 = 0x34324152, - WL_DRM_FORMAT_BGRA8888 = 0x34324142, - WL_DRM_FORMAT_XRGB2101010 = 0x30335258, - WL_DRM_FORMAT_XBGR2101010 = 0x30334258, - WL_DRM_FORMAT_RGBX1010102 = 0x30335852, - WL_DRM_FORMAT_BGRX1010102 = 0x30335842, - WL_DRM_FORMAT_ARGB2101010 = 0x30335241, - WL_DRM_FORMAT_ABGR2101010 = 0x30334241, - WL_DRM_FORMAT_RGBA1010102 = 0x30334152, - WL_DRM_FORMAT_BGRA1010102 = 0x30334142, - WL_DRM_FORMAT_YUYV = 0x56595559, - WL_DRM_FORMAT_YVYU = 0x55595659, - WL_DRM_FORMAT_UYVY = 0x59565955, - WL_DRM_FORMAT_VYUY = 0x59555956, - WL_DRM_FORMAT_AYUV = 0x56555941, - WL_DRM_FORMAT_NV12 = 0x3231564e, - WL_DRM_FORMAT_NV21 = 0x3132564e, - WL_DRM_FORMAT_NV16 = 0x3631564e, - WL_DRM_FORMAT_NV61 = 0x3136564e, - WL_DRM_FORMAT_YUV410 = 0x39565559, - WL_DRM_FORMAT_YVU410 = 0x39555659, - WL_DRM_FORMAT_YUV411 = 0x31315559, - WL_DRM_FORMAT_YVU411 = 0x31315659, - WL_DRM_FORMAT_YUV420 = 0x32315559, - WL_DRM_FORMAT_YVU420 = 0x32315659, - WL_DRM_FORMAT_YUV422 = 0x36315559, - WL_DRM_FORMAT_YVU422 = 0x36315659, - WL_DRM_FORMAT_YUV444 = 0x34325559, - WL_DRM_FORMAT_YVU444 = 0x34325659, -}; -#endif /* WL_DRM_FORMAT_ENUM */ - +struct wl_display; struct wl_drm; +struct wl_resource; struct wl_drm_buffer { struct wl_resource *resource; @@ -96,16 +34,10 @@ wayland_drm_buffer_get(struct wl_drm *drm, struct wl_resource *resource); struct wl_drm * wayland_drm_init(struct wl_display *display, char *device_name, - struct wayland_drm_callbacks *callbacks, void *user_data, + const struct wayland_drm_callbacks *callbacks, void *user_data, uint32_t flags); void wayland_drm_uninit(struct wl_drm *drm); -uint32_t -wayland_drm_buffer_get_format(struct wl_drm_buffer *buffer); - -void * -wayland_drm_buffer_get_buffer(struct wl_drm_buffer *buffer); - #endif diff --git a/lib/mesa/src/egl/wayland/wayland-egl/wayland-egl-backend.h b/lib/mesa/src/egl/wayland/wayland-egl/wayland-egl-backend.h new file mode 100644 index 000000000..82f025cb5 --- /dev/null +++ b/lib/mesa/src/egl/wayland/wayland-egl/wayland-egl-backend.h @@ -0,0 +1,63 @@ +/* + * Copyright © 2011 Benjamin Franzke + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + * + * Authors: + * Benjamin Franzke <benjaminfranzke@googlemail.com> + */ + +#ifndef _WAYLAND_EGL_PRIV_H +#define _WAYLAND_EGL_PRIV_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define WL_EGL_WINDOW_VERSION 3 + +struct wl_surface; + +struct wl_egl_window { + const intptr_t version; + + int width; + int height; + int dx; + int dy; + + int attached_width; + int attached_height; + + void *private; + void (*resize_callback)(struct wl_egl_window *, void *); + void (*destroy_window_callback)(void *); + + struct wl_surface *surface; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/mesa/src/glx/apple/apple_glapi.c b/lib/mesa/src/glx/apple/apple_glapi.c index 4d19f7f6a..f2248ab01 100644 --- a/lib/mesa/src/glx/apple/apple_glapi.c +++ b/lib/mesa/src/glx/apple/apple_glapi.c @@ -41,7 +41,6 @@ #include "main/glheader.h" #include "glapi.h" #include "glapitable.h" -#include "main/dispatch.h" #include "apple_glx.h" #include "apple_xgl_api.h" @@ -61,12 +60,11 @@ static void _apple_glapi_create_table(void) { assert(__applegl_api); memcpy(__applegl_api, __ogl_framework_api, sizeof(struct _glapi_table)); - SET_ReadPixels(__applegl_api, __applegl_glReadPixels); - SET_CopyPixels(__applegl_api, __applegl_glCopyPixels); - SET_CopyColorTable(__applegl_api, __applegl_glCopyColorTable); - SET_DrawBuffer(__applegl_api, __applegl_glDrawBuffer); - SET_DrawBuffers(__applegl_api, __applegl_glDrawBuffers); - SET_Viewport(__applegl_api, __applegl_glViewport); + _glapi_table_patch(__applegl_api, "ReadPixels", __applegl_glReadPixels); + _glapi_table_patch(__applegl_api, "CopyPixels", __applegl_glCopyPixels); + _glapi_table_patch(__applegl_api, "CopyColorTable", __applegl_glCopyColorTable); + _glapi_table_patch(__applegl_api, "DrawBuffers", __applegl_glDrawBuffer); + _glapi_table_patch(__applegl_api, "Viewport", __applegl_glViewport); } void apple_glapi_set_dispatch(void) { diff --git a/lib/mesa/src/glx/apple/apple_glx_context.c b/lib/mesa/src/glx/apple/apple_glx_context.c index 5650b4f32..ff66ed499 100644 --- a/lib/mesa/src/glx/apple/apple_glx_context.c +++ b/lib/mesa/src/glx/apple/apple_glx_context.c @@ -55,6 +55,8 @@ #include "apple_cgl.h" #include "apple_glx_drawable.h" +#include "util/debug.h" + static pthread_mutex_t context_lock = PTHREAD_MUTEX_INITIALIZER; /* @@ -181,7 +183,7 @@ apple_glx_create_context(void **ptr, Display * dpy, int screen, *x11errorptr = false; } - if (getenv("LIBGL_DIAGNOSTIC")) + if (env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) fprintf(stderr, "error: %s\n", apple_cgl.error_string(error)); return true; diff --git a/lib/mesa/src/glx/apple/apple_glx_log.c b/lib/mesa/src/glx/apple/apple_glx_log.c index 5b9a865b6..a3f446c26 100644 --- a/lib/mesa/src/glx/apple/apple_glx_log.c +++ b/lib/mesa/src/glx/apple/apple_glx_log.c @@ -36,12 +36,13 @@ #include <inttypes.h> #include <pthread.h> #include "apple_glx_log.h" +#include "util/debug.h" static bool diagnostic = false; static aslclient aslc; void apple_glx_log_init(void) { - if (getenv("LIBGL_DIAGNOSTIC")) { + if (env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) { diagnostic = true; } diff --git a/lib/mesa/src/glx/apple/apple_glx_pbuffer.c b/lib/mesa/src/glx/apple/apple_glx_pbuffer.c index 142f4cce9..8c94d2010 100644 --- a/lib/mesa/src/glx/apple/apple_glx_pbuffer.c +++ b/lib/mesa/src/glx/apple/apple_glx_pbuffer.c @@ -40,12 +40,14 @@ #include "apple_glx_context.h" #include "apple_glx_drawable.h" +#include <stdbool.h> #include <stdlib.h> #include <pthread.h> #include <assert.h> #include "apple_glx.h" #include "glxconfig.h" #include "apple_cgl.h" +#include "util/debug.h" /* mesa defines in glew.h, Apple in glext.h. * Due to namespace nightmares, just do it here. @@ -208,7 +210,7 @@ get_max_size(int *widthresult, int *heightresult) err = apple_cgl.choose_pixel_format(attr, &pfobj, &vsref); if (kCGLNoError != err) { - if (getenv("LIBGL_DIAGNOSTIC")) { + if (env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) { printf("choose_pixel_format error in %s: %s\n", __func__, apple_cgl.error_string(err)); } @@ -220,7 +222,7 @@ get_max_size(int *widthresult, int *heightresult) err = apple_cgl.create_context(pfobj, NULL, &newcontext); if (kCGLNoError != err) { - if (getenv("LIBGL_DIAGNOSTIC")) { + if (env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) { printf("create_context error in %s: %s\n", __func__, apple_cgl.error_string(err)); } diff --git a/lib/mesa/src/glx/apple/apple_visual.c b/lib/mesa/src/glx/apple/apple_visual.c index d665cd7e0..4a90d77c3 100644 --- a/lib/mesa/src/glx/apple/apple_visual.c +++ b/lib/mesa/src/glx/apple/apple_visual.c @@ -32,6 +32,7 @@ #include <stdlib.h> #include <assert.h> #include <GL/gl.h> +#include <util/debug.h> /* <rdar://problem/6953344> */ #define glTexImage1D glTexImage1D_OSX @@ -82,7 +83,7 @@ apple_visual_create_pfobj(CGLPixelFormatObj * pfobj, const struct glx_config * m int numattr = 0; GLint vsref = 0; CGLError error = 0; - bool use_core_profile = getenv("LIBGL_PROFILE_CORE"); + bool use_core_profile = env_var_as_boolean("LIBGL_PROFILE_CORE", false); if (offscreen) { apple_glx_diagnostic @@ -90,13 +91,13 @@ apple_visual_create_pfobj(CGLPixelFormatObj * pfobj, const struct glx_config * m attr[numattr++] = kCGLPFAOffScreen; } - else if (getenv("LIBGL_ALWAYS_SOFTWARE") != NULL) { + else if (env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false)) { apple_glx_diagnostic ("Software rendering requested. Using kCGLRendererGenericFloatID.\n"); attr[numattr++] = kCGLPFARendererID; attr[numattr++] = kCGLRendererGenericFloatID; } - else if (getenv("LIBGL_ALLOW_SOFTWARE") != NULL) { + else if (env_var_as_boolean("LIBGL_ALLOW_SOFTWARE", false)) { apple_glx_diagnostic ("Software rendering is not being excluded. Not using kCGLPFAAccelerated.\n"); } @@ -190,7 +191,7 @@ apple_visual_create_pfobj(CGLPixelFormatObj * pfobj, const struct glx_config * m if (!*pfobj) { snprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), - "No matching pixelformats found, perhaps try using LIBGL_ALLOW_SOFTWARE\n"); + "No matching pixelformats found, perhaps try setting LIBGL_ALLOW_SOFTWARE=true\n"); fprintf(stderr, "%s", __crashreporter_info_buff__); abort(); } diff --git a/lib/mesa/src/glx/driwindows_glx.c b/lib/mesa/src/glx/driwindows_glx.c index 02d95e7bf..85525431b 100644 --- a/lib/mesa/src/glx/driwindows_glx.c +++ b/lib/mesa/src/glx/driwindows_glx.c @@ -24,6 +24,7 @@ #include "glxclient.h" #include "glx_error.h" #include "dri_common.h" +#include "util/macros.h" #include "windows/xwindowsdri.h" #include "windows/windowsgl.h" @@ -427,7 +428,7 @@ driwindowsBindExtensions(struct driwindows_screen *psc) windows_extensions(&gl_extensions, &wgl_extensions); - for (i = 0; i < sizeof(extensionMap)/sizeof(extensionMap[0]); i++) { + for (i = 0; i < ARRAY_SIZE(extensionMap); i++) { if (strstr(wgl_extensions, extensionMap[i].wglext)) { __glXEnableDirectExtension(&psc->base, extensionMap[i].glxext); InfoMessageF("enabled %s\n", extensionMap[i].glxext); diff --git a/lib/mesa/src/glx/glxext.c b/lib/mesa/src/glx/glxext.c index 9ef7ff5f6..5f23d3717 100644 --- a/lib/mesa/src/glx/glxext.c +++ b/lib/mesa/src/glx/glxext.c @@ -38,6 +38,8 @@ */ #include <assert.h> +#include <stdbool.h> + #include "glxclient.h" #include <X11/extensions/Xext.h> #include <X11/extensions/extutil.h> @@ -47,6 +49,8 @@ #endif #include "glxextensions.h" +#include "util/debug.h" + #include <X11/Xlib-xcb.h> #include <xcb/xcb.h> #include <xcb/glx.h> @@ -524,7 +528,17 @@ __glXInitializeVisualConfigFromTags(struct glx_config * config, int count, config->visualSelectGroup = *bp++; break; case GLX_SWAP_METHOD_OML: - config->swapMethod = *bp++; + if (*bp == GLX_SWAP_UNDEFINED_OML || + *bp == GLX_SWAP_COPY_OML || + *bp == GLX_SWAP_EXCHANGE_OML) { + config->swapMethod = *bp++; + } else { + /* X servers with old HW drivers may return any value here, so + * assume GLX_SWAP_METHOD_UNDEFINED. + */ + config->swapMethod = GLX_SWAP_UNDEFINED_OML; + bp++; + } break; #endif case GLX_SAMPLE_BUFFERS_SGIS: @@ -567,7 +581,7 @@ __glXInitializeVisualConfigFromTags(struct glx_config * config, int count, i = count; break; default: - if(getenv("LIBGL_DIAGNOSTIC")) { + if(env_var_as_boolean("LIBGL_DIAGNOSTIC", false)) { long int tagvalue = *bp++; fprintf(stderr, "WARNING: unknown GLX tag from server: " "tag 0x%lx value 0x%lx\n", tag, tagvalue); @@ -893,8 +907,8 @@ __glXInitialize(Display * dpy) dpyPriv->glXDrawHash = __glxHashCreate(); #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) - glx_direct = (getenv("LIBGL_ALWAYS_INDIRECT") == NULL); - glx_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL); + glx_direct = !env_var_as_boolean("LIBGL_ALWAYS_INDIRECT", false); + glx_accel = !env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); dpyPriv->drawHash = __glxHashCreate(); @@ -906,7 +920,7 @@ __glXInitialize(Display * dpy) #if defined(GLX_USE_DRM) if (glx_direct && glx_accel) { #if defined(HAVE_DRI3) - if (!getenv("LIBGL_DRI3_DISABLE")) + if (!env_var_as_boolean("LIBGL_DRI3_DISABLE", false)) dpyPriv->dri3Display = dri3_create_display(dpy); #endif /* HAVE_DRI3 */ dpyPriv->dri2Display = dri2CreateDisplay(dpy); diff --git a/lib/mesa/src/glx/glxextensions.c b/lib/mesa/src/glx/glxextensions.c index 22b078ce4..6882e442f 100644 --- a/lib/mesa/src/glx/glxextensions.c +++ b/lib/mesa/src/glx/glxextensions.c @@ -139,14 +139,17 @@ static const struct extension_info known_glx_extensions[] = { { GLX(ARB_framebuffer_sRGB), VER(0,0), Y, Y, N, N }, { GLX(ARB_get_proc_address), VER(1,4), Y, N, Y, N }, { GLX(ARB_multisample), VER(1,4), Y, Y, N, N }, - { GLX(ATI_pixel_format_float), VER(0,0), N, N, N, N }, + { GLX(EXT_buffer_age), VER(0,0), Y, N, N, Y }, + { GLX(EXT_create_context_es2_profile), VER(0,0), Y, N, N, N }, + { GLX(EXT_create_context_es_profile), VER(0,0), Y, N, N, N }, + { GLX(EXT_fbconfig_packed_float), VER(0,0), Y, Y, N, N }, + { GLX(EXT_framebuffer_sRGB), VER(0,0), Y, Y, N, N }, { GLX(EXT_import_context), VER(0,0), Y, Y, N, N }, + { GLX(EXT_texture_from_pixmap), VER(0,0), Y, N, N, N }, { GLX(EXT_visual_info), VER(0,0), Y, Y, N, N }, { GLX(EXT_visual_rating), VER(0,0), Y, Y, N, N }, - { GLX(EXT_fbconfig_packed_float), VER(0,0), Y, Y, N, N }, - { GLX(EXT_framebuffer_sRGB), VER(0,0), Y, Y, N, N }, - { GLX(EXT_create_context_es2_profile), VER(0,0), Y, N, N, N }, - { GLX(EXT_create_context_es_profile), VER(0,0), Y, N, N, N }, + { GLX(ATI_pixel_format_float), VER(0,0), N, N, N, N }, + { GLX(INTEL_swap_event), VER(0,0), Y, N, N, N }, { GLX(MESA_copy_sub_buffer), VER(0,0), Y, N, N, N }, { GLX(MESA_multithread_makecurrent),VER(0,0), Y, N, Y, N }, { GLX(MESA_query_renderer), VER(0,0), Y, N, N, Y }, @@ -154,18 +157,15 @@ static const struct extension_info known_glx_extensions[] = { { GLX(NV_float_buffer), VER(0,0), N, N, N, N }, { GLX(OML_swap_method), VER(0,0), Y, Y, N, N }, { GLX(OML_sync_control), VER(0,0), Y, N, N, Y }, - { GLX(SGI_make_current_read), VER(1,3), Y, N, N, N }, - { GLX(SGI_swap_control), VER(0,0), Y, N, N, N }, - { GLX(SGI_video_sync), VER(0,0), Y, N, N, Y }, { GLX(SGIS_multisample), VER(0,0), Y, Y, N, N }, { GLX(SGIX_fbconfig), VER(1,3), Y, Y, N, N }, { GLX(SGIX_pbuffer), VER(1,3), Y, Y, N, N }, { GLX(SGIX_swap_barrier), VER(0,0), N, N, N, N }, { GLX(SGIX_swap_group), VER(0,0), N, N, N, N }, { GLX(SGIX_visual_select_group), VER(0,0), Y, Y, N, N }, - { GLX(EXT_texture_from_pixmap), VER(0,0), Y, N, N, N }, - { GLX(INTEL_swap_event), VER(0,0), Y, N, N, N }, - { GLX(EXT_buffer_age), VER(0,0), Y, N, N, Y }, + { GLX(SGI_make_current_read), VER(1,3), Y, N, N, N }, + { GLX(SGI_swap_control), VER(0,0), Y, N, N, N }, + { GLX(SGI_video_sync), VER(0,0), Y, N, N, Y }, { NULL } }; @@ -190,6 +190,7 @@ static const struct extension_info known_gl_extensions[] = { { GL(ARB_texture_env_combine), VER(1,3), Y, N, N, N }, { GL(ARB_texture_env_crossbar), VER(1,4), Y, N, N, N }, { GL(ARB_texture_env_dot3), VER(1,3), Y, N, N, N }, + { GL(ARB_texture_filter_anisotropic), VER(0,0), Y, N, N, N }, { GL(ARB_texture_mirrored_repeat), VER(1,4), Y, N, N, N }, { GL(ARB_texture_non_power_of_two), VER(1,5), Y, N, N, N }, { GL(ARB_texture_rectangle), VER(0,0), Y, N, N, N }, diff --git a/lib/mesa/src/glx/indirect_glx.c b/lib/mesa/src/glx/indirect_glx.c index 51dd2cacb..4302a8ff2 100644 --- a/lib/mesa/src/glx/indirect_glx.c +++ b/lib/mesa/src/glx/indirect_glx.c @@ -30,9 +30,13 @@ * Kristian Høgsberg (krh@bitplanet.net) */ +#include <stdbool.h> + #include "glapi.h" #include "glxclient.h" +#include "util/debug.h" + #ifndef GLX_USE_APPLEGL extern struct _glapi_table *__glXNewIndirectAPI(void); @@ -371,7 +375,7 @@ indirect_create_context(struct glx_screen *psc, return NULL; } gc->client_state_private = state; - state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL); + state->NoDrawArraysProtocol = env_var_as_boolean("LIBGL_NO_DRAWARRAYS", false); /* ** Create a temporary buffer to hold GLX rendering commands. The size diff --git a/lib/mesa/src/glx/tests/enum_sizes.cpp b/lib/mesa/src/glx/tests/enum_sizes.cpp index 20fc75879..6119dcbc4 100644 --- a/lib/mesa/src/glx/tests/enum_sizes.cpp +++ b/lib/mesa/src/glx/tests/enum_sizes.cpp @@ -36,7 +36,7 @@ #include <gtest/gtest.h> #include <GL/gl.h> extern "C" { -#include "../indirect_size.h" +#include "indirect_size.h" } TEST(ValidEnumSizes, CallLists) diff --git a/lib/mesa/src/intel/compiler/brw_nir_lower_cs_intrinsics.c b/lib/mesa/src/intel/compiler/brw_nir_lower_cs_intrinsics.c new file mode 100644 index 000000000..f9322654e --- /dev/null +++ b/lib/mesa/src/intel/compiler/brw_nir_lower_cs_intrinsics.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "brw_nir.h" +#include "compiler/nir/nir_builder.h" + +struct lower_intrinsics_state { + nir_shader *nir; + struct brw_cs_prog_data *prog_data; + nir_function_impl *impl; + bool progress; + nir_builder builder; + int thread_local_id_index; +}; + +static nir_ssa_def * +read_thread_local_id(struct lower_intrinsics_state *state) +{ + struct brw_cs_prog_data *prog_data = state->prog_data; + nir_builder *b = &state->builder; + nir_shader *nir = state->nir; + const unsigned *sizes = nir->info.cs.local_size; + const unsigned group_size = sizes[0] * sizes[1] * sizes[2]; + + /* Some programs have local_size dimensions so small that the thread local + * ID will always be 0. + */ + if (group_size <= 8) + return nir_imm_int(b, 0); + + if (state->thread_local_id_index == -1) { + state->thread_local_id_index = prog_data->base.nr_params; + uint32_t *param = brw_stage_prog_data_add_params(&prog_data->base, 1); + *param = BRW_PARAM_BUILTIN_THREAD_LOCAL_ID; + nir->num_uniforms += 4; + } + unsigned id_index = state->thread_local_id_index; + + nir_intrinsic_instr *load = + nir_intrinsic_instr_create(nir, nir_intrinsic_load_uniform); + load->num_components = 1; + load->src[0] = nir_src_for_ssa(nir_imm_int(b, 0)); + nir_ssa_dest_init(&load->instr, &load->dest, 1, 32, NULL); + nir_intrinsic_set_base(load, id_index * sizeof(uint32_t)); + nir_intrinsic_set_range(load, sizeof(uint32_t)); + nir_builder_instr_insert(b, &load->instr); + return &load->dest.ssa; +} + +static bool +lower_cs_intrinsics_convert_block(struct lower_intrinsics_state *state, + nir_block *block) +{ + bool progress = false; + nir_builder *b = &state->builder; + nir_shader *nir = state->nir; + + nir_foreach_instr_safe(instr, block) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intrinsic = nir_instr_as_intrinsic(instr); + + b->cursor = nir_after_instr(&intrinsic->instr); + + nir_ssa_def *sysval; + switch (intrinsic->intrinsic) { + case nir_intrinsic_load_local_invocation_index: { + /* We construct the local invocation index from: + * + * gl_LocalInvocationIndex = + * cs_thread_local_id + subgroup_invocation; + */ + nir_ssa_def *thread_local_id = read_thread_local_id(state); + nir_ssa_def *channel = nir_load_subgroup_invocation(b); + sysval = nir_iadd(b, channel, thread_local_id); + break; + } + + case nir_intrinsic_load_local_invocation_id: { + /* We lower gl_LocalInvocationID from gl_LocalInvocationIndex based + * on this formula: + * + * gl_LocalInvocationID.x = + * gl_LocalInvocationIndex % gl_WorkGroupSize.x; + * gl_LocalInvocationID.y = + * (gl_LocalInvocationIndex / gl_WorkGroupSize.x) % + * gl_WorkGroupSize.y; + * gl_LocalInvocationID.z = + * (gl_LocalInvocationIndex / + * (gl_WorkGroupSize.x * gl_WorkGroupSize.y)) % + * gl_WorkGroupSize.z; + */ + unsigned *size = nir->info.cs.local_size; + + nir_ssa_def *local_index = nir_load_local_invocation_index(b); + + nir_const_value uvec3; + uvec3.u32[0] = 1; + uvec3.u32[1] = size[0]; + uvec3.u32[2] = size[0] * size[1]; + nir_ssa_def *div_val = nir_build_imm(b, 3, 32, uvec3); + uvec3.u32[0] = size[0]; + uvec3.u32[1] = size[1]; + uvec3.u32[2] = size[2]; + nir_ssa_def *mod_val = nir_build_imm(b, 3, 32, uvec3); + + sysval = nir_umod(b, nir_udiv(b, local_index, div_val), mod_val); + break; + } + + default: + continue; + } + + nir_ssa_def_rewrite_uses(&intrinsic->dest.ssa, nir_src_for_ssa(sysval)); + nir_instr_remove(&intrinsic->instr); + + state->progress = true; + } + + return progress; +} + +static void +lower_cs_intrinsics_convert_impl(struct lower_intrinsics_state *state) +{ + nir_builder_init(&state->builder, state->impl); + + nir_foreach_block(block, state->impl) { + lower_cs_intrinsics_convert_block(state, block); + } + + nir_metadata_preserve(state->impl, + nir_metadata_block_index | nir_metadata_dominance); +} + +bool +brw_nir_lower_cs_intrinsics(nir_shader *nir, + struct brw_cs_prog_data *prog_data) +{ + assert(nir->info.stage == MESA_SHADER_COMPUTE); + + bool progress = false; + struct lower_intrinsics_state state; + memset(&state, 0, sizeof(state)); + state.nir = nir; + state.prog_data = prog_data; + + state.thread_local_id_index = -1; + + do { + state.progress = false; + nir_foreach_function(function, nir) { + if (function->impl) { + state.impl = function->impl; + lower_cs_intrinsics_convert_impl(&state); + } + } + progress |= state.progress; + } while (state.progress); + + return progress; +} diff --git a/lib/mesa/src/intel/compiler/brw_reg_type.c b/lib/mesa/src/intel/compiler/brw_reg_type.c new file mode 100644 index 000000000..b7fff0867 --- /dev/null +++ b/lib/mesa/src/intel/compiler/brw_reg_type.c @@ -0,0 +1,299 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "brw_reg.h" +#include "brw_eu_defines.h" +#include "common/gen_device_info.h" + +#define INVALID (-1) + +enum hw_reg_type { + BRW_HW_REG_TYPE_UD = 0, + BRW_HW_REG_TYPE_D = 1, + BRW_HW_REG_TYPE_UW = 2, + BRW_HW_REG_TYPE_W = 3, + BRW_HW_REG_TYPE_F = 7, + GEN8_HW_REG_TYPE_UQ = 8, + GEN8_HW_REG_TYPE_Q = 9, + + BRW_HW_REG_TYPE_UB = 4, + BRW_HW_REG_TYPE_B = 5, + GEN7_HW_REG_TYPE_DF = 6, + GEN8_HW_REG_TYPE_HF = 10, +}; + +enum hw_imm_type { + BRW_HW_IMM_TYPE_UD = 0, + BRW_HW_IMM_TYPE_D = 1, + BRW_HW_IMM_TYPE_UW = 2, + BRW_HW_IMM_TYPE_W = 3, + BRW_HW_IMM_TYPE_F = 7, + GEN8_HW_IMM_TYPE_UQ = 8, + GEN8_HW_IMM_TYPE_Q = 9, + + BRW_HW_IMM_TYPE_UV = 4, + BRW_HW_IMM_TYPE_VF = 5, + BRW_HW_IMM_TYPE_V = 6, + GEN8_HW_IMM_TYPE_DF = 10, + GEN8_HW_IMM_TYPE_HF = 11, +}; + +static const struct { + enum hw_reg_type reg_type; + enum hw_imm_type imm_type; +} gen4_hw_type[] = { + [BRW_REGISTER_TYPE_DF] = { GEN7_HW_REG_TYPE_DF, GEN8_HW_IMM_TYPE_DF }, + [BRW_REGISTER_TYPE_F] = { BRW_HW_REG_TYPE_F, BRW_HW_IMM_TYPE_F }, + [BRW_REGISTER_TYPE_HF] = { GEN8_HW_REG_TYPE_HF, GEN8_HW_IMM_TYPE_HF }, + [BRW_REGISTER_TYPE_VF] = { INVALID, BRW_HW_IMM_TYPE_VF }, + + [BRW_REGISTER_TYPE_Q] = { GEN8_HW_REG_TYPE_Q, GEN8_HW_IMM_TYPE_Q }, + [BRW_REGISTER_TYPE_UQ] = { GEN8_HW_REG_TYPE_UQ, GEN8_HW_IMM_TYPE_UQ }, + [BRW_REGISTER_TYPE_D] = { BRW_HW_REG_TYPE_D, BRW_HW_IMM_TYPE_D }, + [BRW_REGISTER_TYPE_UD] = { BRW_HW_REG_TYPE_UD, BRW_HW_IMM_TYPE_UD }, + [BRW_REGISTER_TYPE_W] = { BRW_HW_REG_TYPE_W, BRW_HW_IMM_TYPE_W }, + [BRW_REGISTER_TYPE_UW] = { BRW_HW_REG_TYPE_UW, BRW_HW_IMM_TYPE_UW }, + [BRW_REGISTER_TYPE_B] = { BRW_HW_REG_TYPE_B, INVALID }, + [BRW_REGISTER_TYPE_UB] = { BRW_HW_REG_TYPE_UB, INVALID }, + [BRW_REGISTER_TYPE_V] = { INVALID, BRW_HW_IMM_TYPE_V }, + [BRW_REGISTER_TYPE_UV] = { INVALID, BRW_HW_IMM_TYPE_UV }, +}; + +/* SNB adds 3-src instructions (MAD and LRP) that only operate on floats, so + * the types were implied. IVB adds BFE and BFI2 that operate on doublewords + * and unsigned doublewords, so a new field is also available in the da3src + * struct (part of struct brw_instruction.bits1 in brw_structs.h) to select + * dst and shared-src types. + * + * CNL adds support for 3-src instructions in align1 mode, and with it support + * for most register types. + */ +enum hw_3src_reg_type { + GEN7_3SRC_TYPE_F = 0, + GEN7_3SRC_TYPE_D = 1, + GEN7_3SRC_TYPE_UD = 2, + GEN7_3SRC_TYPE_DF = 3, + + /** When ExecutionDatatype is 1: @{ */ + GEN10_ALIGN1_3SRC_REG_TYPE_HF = 0b000, + GEN10_ALIGN1_3SRC_REG_TYPE_F = 0b001, + GEN10_ALIGN1_3SRC_REG_TYPE_DF = 0b010, + /** @} */ + + /** When ExecutionDatatype is 0: @{ */ + GEN10_ALIGN1_3SRC_REG_TYPE_UD = 0b000, + GEN10_ALIGN1_3SRC_REG_TYPE_D = 0b001, + GEN10_ALIGN1_3SRC_REG_TYPE_UW = 0b010, + GEN10_ALIGN1_3SRC_REG_TYPE_W = 0b011, + GEN10_ALIGN1_3SRC_REG_TYPE_UB = 0b100, + GEN10_ALIGN1_3SRC_REG_TYPE_B = 0b101, + /** @} */ +}; + +static const struct hw_3src_type { + enum hw_3src_reg_type reg_type; + enum gen10_align1_3src_exec_type exec_type; +} gen7_hw_3src_type[] = { + [0 ... BRW_REGISTER_TYPE_LAST] = { INVALID }, + + [BRW_REGISTER_TYPE_F] = { GEN7_3SRC_TYPE_F }, + [BRW_REGISTER_TYPE_D] = { GEN7_3SRC_TYPE_D }, + [BRW_REGISTER_TYPE_UD] = { GEN7_3SRC_TYPE_UD }, + [BRW_REGISTER_TYPE_DF] = { GEN7_3SRC_TYPE_DF }, +}, gen10_hw_3src_align1_type[] = { +#define E(x) BRW_ALIGN1_3SRC_EXEC_TYPE_##x + [0 ... BRW_REGISTER_TYPE_LAST] = { INVALID }, + + [BRW_REGISTER_TYPE_DF] = { GEN10_ALIGN1_3SRC_REG_TYPE_DF, E(FLOAT) }, + [BRW_REGISTER_TYPE_F] = { GEN10_ALIGN1_3SRC_REG_TYPE_F, E(FLOAT) }, + [BRW_REGISTER_TYPE_HF] = { GEN10_ALIGN1_3SRC_REG_TYPE_HF, E(FLOAT) }, + + [BRW_REGISTER_TYPE_D] = { GEN10_ALIGN1_3SRC_REG_TYPE_D, E(INT) }, + [BRW_REGISTER_TYPE_UD] = { GEN10_ALIGN1_3SRC_REG_TYPE_UD, E(INT) }, + [BRW_REGISTER_TYPE_W] = { GEN10_ALIGN1_3SRC_REG_TYPE_W, E(INT) }, + [BRW_REGISTER_TYPE_UW] = { GEN10_ALIGN1_3SRC_REG_TYPE_UW, E(INT) }, + [BRW_REGISTER_TYPE_B] = { GEN10_ALIGN1_3SRC_REG_TYPE_B, E(INT) }, + [BRW_REGISTER_TYPE_UB] = { GEN10_ALIGN1_3SRC_REG_TYPE_UB, E(INT) }, +#undef E +}; + +/** + * Convert a brw_reg_type enumeration value into the hardware representation. + * + * The hardware encoding may depend on whether the value is an immediate. + */ +unsigned +brw_reg_type_to_hw_type(const struct gen_device_info *devinfo, + enum brw_reg_file file, + enum brw_reg_type type) +{ + assert(type < ARRAY_SIZE(gen4_hw_type)); + + if (file == BRW_IMMEDIATE_VALUE) { + assert(gen4_hw_type[type].imm_type != (enum hw_imm_type)INVALID); + return gen4_hw_type[type].imm_type; + } else { + assert(gen4_hw_type[type].reg_type != (enum hw_reg_type)INVALID); + return gen4_hw_type[type].reg_type; + } +} + +/** + * Convert the hardware representation into a brw_reg_type enumeration value. + * + * The hardware encoding may depend on whether the value is an immediate. + */ +enum brw_reg_type +brw_hw_type_to_reg_type(const struct gen_device_info *devinfo, + enum brw_reg_file file, unsigned hw_type) +{ + if (file == BRW_IMMEDIATE_VALUE) { + for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) { + if (gen4_hw_type[i].imm_type == (enum hw_imm_type)hw_type) { + return i; + } + } + } else { + for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) { + if (gen4_hw_type[i].reg_type == (enum hw_reg_type)hw_type) { + return i; + } + } + } + unreachable("not reached"); +} + +/** + * Convert a brw_reg_type enumeration value into the hardware representation + * for a 3-src align16 instruction + */ +unsigned +brw_reg_type_to_a16_hw_3src_type(const struct gen_device_info *devinfo, + enum brw_reg_type type) +{ + assert(type < ARRAY_SIZE(gen7_hw_3src_type)); + assert(gen7_hw_3src_type[type].reg_type != (enum hw_3src_reg_type)INVALID); + return gen7_hw_3src_type[type].reg_type; +} + +/** + * Convert a brw_reg_type enumeration value into the hardware representation + * for a 3-src align1 instruction + */ +unsigned +brw_reg_type_to_a1_hw_3src_type(const struct gen_device_info *devinfo, + enum brw_reg_type type) +{ + assert(type < ARRAY_SIZE(gen10_hw_3src_align1_type)); + assert(gen10_hw_3src_align1_type[type].reg_type != (enum hw_3src_reg_type)INVALID); + return gen10_hw_3src_align1_type[type].reg_type; +} + +/** + * Convert the hardware representation for a 3-src align16 instruction into a + * brw_reg_type enumeration value. + */ +enum brw_reg_type +brw_a16_hw_3src_type_to_reg_type(const struct gen_device_info *devinfo, + unsigned hw_type) +{ + for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) { + if (gen7_hw_3src_type[i].reg_type == hw_type) { + return i; + } + } + unreachable("not reached"); +} + +/** + * Convert the hardware representation for a 3-src align1 instruction into a + * brw_reg_type enumeration value. + */ +enum brw_reg_type +brw_a1_hw_3src_type_to_reg_type(const struct gen_device_info *devinfo, + unsigned hw_type, unsigned exec_type) +{ + for (enum brw_reg_type i = 0; i <= BRW_REGISTER_TYPE_LAST; i++) { + if (gen10_hw_3src_align1_type[i].reg_type == hw_type && + gen10_hw_3src_align1_type[i].exec_type == exec_type) { + return i; + } + } + unreachable("not reached"); +} + +/** + * Return the element size given a register type. + */ +unsigned +brw_reg_type_to_size(enum brw_reg_type type) +{ + static const unsigned type_size[] = { + [BRW_REGISTER_TYPE_DF] = 8, + [BRW_REGISTER_TYPE_F] = 4, + [BRW_REGISTER_TYPE_HF] = 2, + [BRW_REGISTER_TYPE_VF] = 4, + + [BRW_REGISTER_TYPE_Q] = 8, + [BRW_REGISTER_TYPE_UQ] = 8, + [BRW_REGISTER_TYPE_D] = 4, + [BRW_REGISTER_TYPE_UD] = 4, + [BRW_REGISTER_TYPE_W] = 2, + [BRW_REGISTER_TYPE_UW] = 2, + [BRW_REGISTER_TYPE_B] = 1, + [BRW_REGISTER_TYPE_UB] = 1, + [BRW_REGISTER_TYPE_V] = 2, + [BRW_REGISTER_TYPE_UV] = 2, + }; + return type_size[type]; +} + +/** + * Converts a BRW_REGISTER_TYPE_* enum to a short string (F, UD, and so on). + * + * This is different than reg_encoding from brw_disasm.c in that it operates + * on the abstract enum values, rather than the generation-specific encoding. + */ +const char * +brw_reg_type_to_letters(enum brw_reg_type type) +{ + static const char letters[][3] = { + [BRW_REGISTER_TYPE_DF] = "DF", + [BRW_REGISTER_TYPE_F] = "F", + [BRW_REGISTER_TYPE_HF] = "HF", + [BRW_REGISTER_TYPE_VF] = "VF", + + [BRW_REGISTER_TYPE_Q] = "Q", + [BRW_REGISTER_TYPE_UQ] = "UQ", + [BRW_REGISTER_TYPE_D] = "D", + [BRW_REGISTER_TYPE_UD] = "UD", + [BRW_REGISTER_TYPE_W] = "W", + [BRW_REGISTER_TYPE_UW] = "UW", + [BRW_REGISTER_TYPE_B] = "B", + [BRW_REGISTER_TYPE_UB] = "UB", + [BRW_REGISTER_TYPE_V] = "V", + [BRW_REGISTER_TYPE_UV] = "UV", + }; + assert(type < ARRAY_SIZE(letters)); + return letters[type]; +} diff --git a/lib/mesa/src/intel/compiler/brw_reg_type.h b/lib/mesa/src/intel/compiler/brw_reg_type.h new file mode 100644 index 000000000..3bc9a36e7 --- /dev/null +++ b/lib/mesa/src/intel/compiler/brw_reg_type.h @@ -0,0 +1,117 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS 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 BRW_REG_TYPE_H +#define BRW_REG_TYPE_H + +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_FUNC_ATTRIBUTE_PURE +#define ATTRIBUTE_PURE __attribute__((__pure__)) +#else +#define ATTRIBUTE_PURE +#endif + +enum brw_reg_file; +struct gen_device_info; + +/* + * The ordering has been chosen so that no enum value is the same as a + * compatible hardware encoding. + */ +enum PACKED brw_reg_type { + /** Floating-point types: @{ */ + BRW_REGISTER_TYPE_DF, + BRW_REGISTER_TYPE_F, + BRW_REGISTER_TYPE_HF, + BRW_REGISTER_TYPE_VF, + /** @} */ + + /** Integer types: @{ */ + BRW_REGISTER_TYPE_Q, + BRW_REGISTER_TYPE_UQ, + BRW_REGISTER_TYPE_D, + BRW_REGISTER_TYPE_UD, + BRW_REGISTER_TYPE_W, + BRW_REGISTER_TYPE_UW, + BRW_REGISTER_TYPE_B, + BRW_REGISTER_TYPE_UB, + BRW_REGISTER_TYPE_V, + BRW_REGISTER_TYPE_UV, + /** @} */ + + BRW_REGISTER_TYPE_LAST = BRW_REGISTER_TYPE_UV +}; + +static inline bool +brw_reg_type_is_floating_point(enum brw_reg_type type) +{ + switch (type) { + case BRW_REGISTER_TYPE_DF: + case BRW_REGISTER_TYPE_F: + case BRW_REGISTER_TYPE_HF: + return true; + default: + return false; + } +} + +unsigned +brw_reg_type_to_hw_type(const struct gen_device_info *devinfo, + enum brw_reg_file file, enum brw_reg_type type); + +enum brw_reg_type ATTRIBUTE_PURE +brw_hw_type_to_reg_type(const struct gen_device_info *devinfo, + enum brw_reg_file file, unsigned hw_type); + +unsigned +brw_reg_type_to_a16_hw_3src_type(const struct gen_device_info *devinfo, + enum brw_reg_type type); + +unsigned +brw_reg_type_to_a1_hw_3src_type(const struct gen_device_info *devinfo, + enum brw_reg_type type); + +enum brw_reg_type +brw_a16_hw_3src_type_to_reg_type(const struct gen_device_info *devinfo, + unsigned hw_type); + +enum brw_reg_type +brw_a1_hw_3src_type_to_reg_type(const struct gen_device_info *devinfo, + unsigned hw_type, unsigned exec_type); + +unsigned +brw_reg_type_to_size(enum brw_reg_type type); + +const char * +brw_reg_type_to_letters(enum brw_reg_type type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/mesa/src/mesa/drivers/SConscript b/lib/mesa/src/mesa/drivers/SConscript index 476425be2..f54991033 100644 --- a/lib/mesa/src/mesa/drivers/SConscript +++ b/lib/mesa/src/mesa/drivers/SConscript @@ -7,6 +7,5 @@ if env['x11']: if env['dri']: SConscript([ - 'dri/common/xmlpool/SConscript', 'dri/common/SConscript', ]) diff --git a/lib/mesa/src/mesa/drivers/dri/common/Makefile.sources b/lib/mesa/src/mesa/drivers/dri/common/Makefile.sources index 9d3cdd38f..d592e99b8 100644 --- a/lib/mesa/src/mesa/drivers/dri/common/Makefile.sources +++ b/lib/mesa/src/mesa/drivers/dri/common/Makefile.sources @@ -4,10 +4,6 @@ DRI_COMMON_FILES := \ dri_util.c \ dri_util.h -XMLCONFIG_FILES := \ - xmlconfig.c \ - xmlconfig.h - # Paths are relative to MESA_TOP. mesa_dri_common_INCLUDES := \ include \ @@ -15,7 +11,8 @@ mesa_dri_common_INCLUDES := \ src/egl/main \ src/mapi \ src/mesa \ - src/mesa/drivers/dri/common + src/mesa/drivers/dri/common \ + src/util megadriver_stub_FILES := \ megadriver_stub.c diff --git a/lib/mesa/src/mesa/drivers/dri/common/SConscript b/lib/mesa/src/mesa/drivers/dri/common/SConscript index 52d201f89..defd6bfb4 100644 --- a/lib/mesa/src/mesa/drivers/dri/common/SConscript +++ b/lib/mesa/src/mesa/drivers/dri/common/SConscript @@ -7,7 +7,6 @@ drienv = env.Clone() drienv.Replace(CPPPATH = [ '#src/mesa/drivers/dri/common', - xmlpool_options.dir.dir, # Dir to generated xmlpool/options.h '#include', '#include/GL/internal', '#src', @@ -26,13 +25,10 @@ drienv.Replace(CPPPATH = [ '#src/mesa/swrast_setup', '#src/egl/main', '#src/egl/drivers/dri', + xmlpool_options.dir.dir, ]) -drienv.AppendUnique(LIBS = [ - 'expat', -]) - -sources = drienv.ParseSourceList('Makefile.sources', ['DRI_COMMON_FILES', 'XMLCONFIG_FILES' ]) +sources = drienv.ParseSourceList('Makefile.sources', ['DRI_COMMON_FILES']) dri_common = drienv.ConvenienceLibrary( target = 'dri_common', diff --git a/lib/mesa/src/mesa/drivers/dri/common/utils.c b/lib/mesa/src/mesa/drivers/dri/common/utils.c index c37d446a1..e944754a4 100644 --- a/lib/mesa/src/mesa/drivers/dri/common/utils.c +++ b/lib/mesa/src/mesa/drivers/dri/common/utils.c @@ -284,8 +284,9 @@ driCreateConfigs(mesa_format format, modes->transparentIndex = GLX_DONT_CARE; modes->rgbMode = GL_TRUE; - if ( db_modes[i] == GLX_NONE ) { + if (db_modes[i] == __DRI_ATTRIB_SWAP_NONE) { modes->doubleBufferMode = GL_FALSE; + modes->swapMethod = __DRI_ATTRIB_SWAP_UNDEFINED; } else { modes->doubleBufferMode = GL_TRUE; @@ -403,7 +404,6 @@ static const struct { unsigned int attrib, offset; } attribMap[] = { * so the iterator includes them though.*/ __ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level), __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level), - __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level) }; @@ -428,10 +428,6 @@ driGetConfigAttribIndex(const __DRIconfig *config, else *value = 0; break; - case __DRI_ATTRIB_SWAP_METHOD: - /* XXX no return value??? */ - break; - default: /* any other int-sized field */ *value = *(unsigned int *) diff --git a/lib/mesa/src/mesa/main/barrier.h b/lib/mesa/src/mesa/main/barrier.h index d54c02af6..53ecf863f 100644 --- a/lib/mesa/src/mesa/main/barrier.h +++ b/lib/mesa/src/mesa/main/barrier.h @@ -45,6 +45,9 @@ void GLAPIENTRY _mesa_MemoryBarrier(GLbitfield barriers); void GLAPIENTRY +_mesa_MemoryBarrierByRegion_no_error(GLbitfield barriers); + +void GLAPIENTRY _mesa_MemoryBarrierByRegion(GLbitfield barriers); void GLAPIENTRY diff --git a/lib/mesa/src/mesa/main/condrender.h b/lib/mesa/src/mesa/main/condrender.h index 90d7fb722..e7672512f 100644 --- a/lib/mesa/src/mesa/main/condrender.h +++ b/lib/mesa/src/mesa/main/condrender.h @@ -31,9 +31,15 @@ #include "context.h" +void GLAPIENTRY +_mesa_BeginConditionalRender_no_error(GLuint queryId, GLenum mode); + extern void GLAPIENTRY _mesa_BeginConditionalRender(GLuint queryId, GLenum mode); +void APIENTRY +_mesa_EndConditionalRender_no_error(void); + extern void APIENTRY _mesa_EndConditionalRender(void); diff --git a/lib/mesa/src/mesa/main/execmem.h b/lib/mesa/src/mesa/main/execmem.h new file mode 100644 index 000000000..bc51a8c84 --- /dev/null +++ b/lib/mesa/src/mesa/main/execmem.h @@ -0,0 +1,37 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef EXECMEM_H +#define EXECMEM_H + + +extern void * +_mesa_exec_malloc(GLuint size); + +extern void +_mesa_exec_free(void *addr); + + +#endif /* EXECMEM_H */ diff --git a/lib/mesa/src/mesa/main/extensions.c b/lib/mesa/src/mesa/main/extensions.c index 62a731675..f185aa5aa 100644 --- a/lib/mesa/src/mesa/main/extensions.c +++ b/lib/mesa/src/mesa/main/extensions.c @@ -130,6 +130,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.ARB_texture_env_combine = GL_TRUE; ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE; ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE; + ctx->Extensions.ARB_texture_filter_anisotropic = GL_TRUE; #ifdef TEXTURE_FLOAT_ENABLED ctx->Extensions.ARB_texture_float = GL_TRUE; #endif @@ -176,10 +177,8 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE; ctx->Extensions.OES_standard_derivatives = GL_TRUE; ctx->Extensions.TDFX_texture_compression_FXT1 = GL_TRUE; - if (ctx->Mesa_DXTn) { - ctx->Extensions.ANGLE_texture_compression_dxt = GL_TRUE; - ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; - } + ctx->Extensions.ANGLE_texture_compression_dxt = GL_TRUE; + ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; } /** diff --git a/lib/mesa/src/mesa/main/externalobjects.c b/lib/mesa/src/mesa/main/externalobjects.c new file mode 100644 index 000000000..e70280c96 --- /dev/null +++ b/lib/mesa/src/mesa/main/externalobjects.c @@ -0,0 +1,640 @@ +/* + * Copyright © 2016 Red Hat. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "macros.h" +#include "mtypes.h" +#include "externalobjects.h" +#include "teximage.h" +#include "texobj.h" +#include "glformats.h" +#include "texstorage.h" + +/** + * Allocate and initialize a new memory object. But don't put it into the + * memory object hash table. + * + * Called via ctx->Driver.NewMemoryObject, unless overridden by a device + * driver. + * + * \return pointer to new memory object. + */ +static struct gl_memory_object * +_mesa_new_memory_object(struct gl_context *ctx, GLuint name) +{ + struct gl_memory_object *obj = MALLOC_STRUCT(gl_memory_object); + if (!obj) + return NULL; + + _mesa_initialize_memory_object(ctx, obj, name); + return obj; +} + +/** + * Delete a memory object. Called via ctx->Driver.DeleteMemory(). + * Not removed from hash table here. + */ +void +_mesa_delete_memory_object(struct gl_context *ctx, + struct gl_memory_object *memObj) +{ + free(memObj); +} + +void +_mesa_init_memory_object_functions(struct dd_function_table *driver) +{ + driver->NewMemoryObject = _mesa_new_memory_object; + driver->DeleteMemoryObject = _mesa_delete_memory_object; +} + +/** + * Initialize a buffer object to default values. + */ +void +_mesa_initialize_memory_object(struct gl_context *ctx, + struct gl_memory_object *obj, + GLuint name) +{ + memset(obj, 0, sizeof(struct gl_memory_object)); + obj->Name = name; + obj->Dedicated = GL_FALSE; +} + +void GLAPIENTRY +_mesa_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObjects) +{ + GET_CURRENT_CONTEXT(ctx); + + if (MESA_VERBOSE & (VERBOSE_API)) { + _mesa_debug(ctx, "glDeleteMemoryObjectsEXT(%d, %p)\n", n, + memoryObjects); + } + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDeleteMemoryObjectsEXT(unsupported)"); + return; + } + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteMemoryObjectsEXT(n < 0)"); + return; + } + + if (!memoryObjects) + return; + + _mesa_HashLockMutex(ctx->Shared->MemoryObjects); + for (GLint i = 0; i < n; i++) { + if (memoryObjects[i] > 0) { + struct gl_memory_object *delObj + = _mesa_lookup_memory_object_locked(ctx, memoryObjects[i]); + + if (delObj) { + _mesa_HashRemoveLocked(ctx->Shared->MemoryObjects, + memoryObjects[i]); + ctx->Driver.DeleteMemoryObject(ctx, delObj); + } + } + } + _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects); +} + +GLboolean GLAPIENTRY +_mesa_IsMemoryObjectEXT(GLuint memoryObject) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glIsMemoryObjectEXT(unsupported)"); + return GL_FALSE; + } + + struct gl_memory_object *obj = + _mesa_lookup_memory_object(ctx, memoryObject); + + return obj ? GL_TRUE : GL_FALSE; +} + +void GLAPIENTRY +_mesa_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects) +{ + GET_CURRENT_CONTEXT(ctx); + + const char *func = "glCreateMemoryObjectsEXT"; + + if (MESA_VERBOSE & (VERBOSE_API)) + _mesa_debug(ctx, "%s(%d, %p)", func, n, memoryObjects); + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glCreateMemoryObjectsEXT(unsupported)"); + return; + } + + if (n < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func); + return; + } + + if (!memoryObjects) + return; + + _mesa_HashLockMutex(ctx->Shared->MemoryObjects); + GLuint first = _mesa_HashFindFreeKeyBlock(ctx->Shared->MemoryObjects, n); + if (first) { + for (GLsizei i = 0; i < n; i++) { + struct gl_memory_object *memObj; + + memoryObjects[i] = first + i; + + /* allocate memory object */ + memObj = ctx->Driver.NewMemoryObject(ctx, memoryObjects[i]); + if (!memObj) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func); + _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects); + return; + } + + /* insert into hash table */ + _mesa_HashInsertLocked(ctx->Shared->MemoryObjects, + memoryObjects[i], + memObj); + } + } + + _mesa_HashUnlockMutex(ctx->Shared->MemoryObjects); +} + +void GLAPIENTRY +_mesa_MemoryObjectParameterivEXT(GLuint memoryObject, + GLenum pname, + const GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_memory_object *memObj; + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMemoryObjectParameterivEXT(unsupported)"); + return; + } + + memObj = _mesa_lookup_memory_object(ctx, memoryObject); + if (!memObj) + return; + + if (memObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glMemoryObjectParameterivEXT(memoryObject is immutable"); + return; + } + + switch (pname) { + case GL_DEDICATED_MEMORY_OBJECT_EXT: + memObj->Dedicated = (GLboolean) params[0]; + break; + case GL_PROTECTED_MEMORY_OBJECT_EXT: + /* EXT_protected_textures not supported */ + goto invalid_pname; + default: + goto invalid_pname; + } + return; + +invalid_pname: + _mesa_error(ctx, GL_INVALID_ENUM, + "glMemoryObjectParameterivEXT(pname=0x%x)", pname); +} + +void GLAPIENTRY +_mesa_GetMemoryObjectParameterivEXT(GLuint memoryObject, + GLenum pname, + GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + struct gl_memory_object *memObj; + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetMemoryObjectParameterivEXT(unsupported)"); + return; + } + + memObj = _mesa_lookup_memory_object(ctx, memoryObject); + if (!memObj) + return; + + switch (pname) { + case GL_DEDICATED_MEMORY_OBJECT_EXT: + *params = (GLint) memObj->Dedicated; + break; + case GL_PROTECTED_MEMORY_OBJECT_EXT: + /* EXT_protected_textures not supported */ + goto invalid_pname; + default: + goto invalid_pname; + } + return; + +invalid_pname: + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetMemoryObjectParameterivEXT(pname=0x%x)", pname); +} + +static struct gl_memory_object * +lookup_memory_object_err(struct gl_context *ctx, unsigned memory, + const char* func) +{ + if (memory == 0) { + _mesa_error(ctx, GL_INVALID_VALUE, "%s(memory=0)", func); + return NULL; + } + + struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory); + if (!memObj) + return NULL; + + if (!memObj->Immutable) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no associated memory)", + func); + return NULL; + } + + return memObj; +} + +/** + * Helper used by _mesa_TexStorageMem1/2/3DEXT(). + */ +static void +texstorage_memory(GLuint dims, GLenum target, GLsizei levels, + GLenum internalFormat, GLsizei width, GLsizei height, + GLsizei depth, GLuint memory, GLuint64 offset, + const char *func) +{ + struct gl_texture_object *texObj; + struct gl_memory_object *memObj; + + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); + return; + } + + texObj = _mesa_get_current_tex_object(ctx, target); + if (!texObj) + return; + + memObj = lookup_memory_object_err(ctx, memory, func); + if (!memObj) + return; + + _mesa_texture_storage_memory(ctx, dims, texObj, memObj, target, + levels, internalFormat, + width, height, depth, offset, false); +} + +static void +texstorage_memory_ms(GLuint dims, GLenum target, GLsizei samples, + GLenum internalFormat, GLsizei width, GLsizei height, + GLsizei depth, GLboolean fixedSampleLocations, + GLuint memory, GLuint64 offset, const char* func) +{ + struct gl_texture_object *texObj; + struct gl_memory_object *memObj; + + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); + return; + } + + texObj = _mesa_get_current_tex_object(ctx, target); + if (!texObj) + return; + + memObj = lookup_memory_object_err(ctx, memory, func); + if (!memObj) + return; + + _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, target, samples, + internalFormat, width, height, depth, + fixedSampleLocations, offset, func); +} + +/** + * Helper used by _mesa_TextureStorageMem1/2/3DEXT(). + */ +static void +texturestorage_memory(GLuint dims, GLuint texture, GLsizei levels, + GLenum internalFormat, GLsizei width, GLsizei height, + GLsizei depth, GLuint memory, GLuint64 offset, + const char *func) +{ + struct gl_texture_object *texObj; + struct gl_memory_object *memObj; + + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); + return; + } + + texObj = _mesa_lookup_texture(ctx, texture); + if (!texObj) + return; + + memObj = lookup_memory_object_err(ctx, memory, func); + if (!memObj) + return; + + _mesa_texture_storage_memory(ctx, dims, texObj, memObj, texObj->Target, + levels, internalFormat, + width, height, depth, offset, true); +} + +static void +texturestorage_memory_ms(GLuint dims, GLuint texture, GLsizei samples, + GLenum internalFormat, GLsizei width, GLsizei height, + GLsizei depth, GLboolean fixedSampleLocations, + GLuint memory, GLuint64 offset, const char* func) +{ + struct gl_texture_object *texObj; + struct gl_memory_object *memObj; + + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.EXT_memory_object) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); + return; + } + + texObj = _mesa_lookup_texture(ctx, texture); + if (!texObj) + return; + + memObj = lookup_memory_object_err(ctx, memory, func); + if (!memObj) + return; + + _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, texObj->Target, + samples, internalFormat, width, height, + depth, fixedSampleLocations, offset, func); +} + +void GLAPIENTRY +_mesa_TexStorageMem2DEXT(GLenum target, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLuint memory, + GLuint64 offset) +{ + texstorage_memory(2, target, levels, internalFormat, width, height, 1, + memory, offset, "glTexStorageMem2DEXT"); +} + +void GLAPIENTRY +_mesa_TexStorageMem2DMultisampleEXT(GLenum target, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLboolean fixedSampleLocations, + GLuint memory, + GLuint64 offset) +{ + texstorage_memory_ms(2, target, samples, internalFormat, width, height, 1, + fixedSampleLocations, memory, offset, + "glTexStorageMem2DMultisampleEXT"); +} + +void GLAPIENTRY +_mesa_TexStorageMem3DEXT(GLenum target, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLuint memory, + GLuint64 offset) +{ + texstorage_memory(3, target, levels, internalFormat, width, height, depth, + memory, offset, "glTexStorageMem3DEXT"); +} + +void GLAPIENTRY +_mesa_TexStorageMem3DMultisampleEXT(GLenum target, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLboolean fixedSampleLocations, + GLuint memory, + GLuint64 offset) +{ + texstorage_memory_ms(3, target, samples, internalFormat, width, height, + depth, fixedSampleLocations, memory, offset, + "glTexStorageMem3DMultisampleEXT"); +} + +void GLAPIENTRY +_mesa_TextureStorageMem2DEXT(GLuint texture, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLuint memory, + GLuint64 offset) +{ + texturestorage_memory(2, texture, levels, internalFormat, width, height, 1, + memory, offset, "glTexureStorageMem2DEXT"); +} + +void GLAPIENTRY +_mesa_TextureStorageMem2DMultisampleEXT(GLuint texture, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLboolean fixedSampleLocations, + GLuint memory, + GLuint64 offset) +{ + texturestorage_memory_ms(2, texture, samples, internalFormat, width, height, + 1, fixedSampleLocations, memory, offset, + "glTextureStorageMem2DMultisampleEXT"); +} + +void GLAPIENTRY +_mesa_TextureStorageMem3DEXT(GLuint texture, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLuint memory, + GLuint64 offset) +{ + texturestorage_memory(3, texture, levels, internalFormat, width, height, + depth, memory, offset, "glTextureStorageMem3DEXT"); +} + +void GLAPIENTRY +_mesa_TextureStorageMem3DMultisampleEXT(GLuint texture, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLboolean fixedSampleLocations, + GLuint memory, + GLuint64 offset) +{ + texturestorage_memory_ms(3, texture, samples, internalFormat, width, height, + depth, fixedSampleLocations, memory, offset, + "glTextureStorageMem3DMultisampleEXT"); +} + +void GLAPIENTRY +_mesa_TexStorageMem1DEXT(GLenum target, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLuint memory, + GLuint64 offset) +{ + texstorage_memory(1, target, levels, internalFormat, width, 1, 1, memory, + offset, "glTexStorageMem1DEXT"); +} + +void GLAPIENTRY +_mesa_TextureStorageMem1DEXT(GLuint texture, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLuint memory, + GLuint64 offset) +{ + texturestorage_memory(1, texture, levels, internalFormat, width, 1, 1, + memory, offset, "glTextureStorageMem1DEXT"); +} + +void GLAPIENTRY +_mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores) +{ + +} + +void GLAPIENTRY +_mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores) +{ + +} + +GLboolean GLAPIENTRY +_mesa_IsSemaphoreEXT(GLuint semaphore) +{ + return GL_FALSE; +} + +void GLAPIENTRY +_mesa_SemaphoreParameterui64vEXT(GLuint semaphore, + GLenum pname, + const GLuint64 *params) +{ + +} + +void GLAPIENTRY +_mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore, + GLenum pname, + GLuint64 *params) +{ + +} + +void GLAPIENTRY +_mesa_WaitSemaphoreEXT(GLuint semaphore, + GLuint numBufferBarriers, + const GLuint *buffers, + GLuint numTextureBarriers, + const GLuint *textures, + const GLenum *srcLayouts) +{ + +} + +void GLAPIENTRY +_mesa_SignalSemaphoreEXT(GLuint semaphore, + GLuint numBufferBarriers, + const GLuint *buffers, + GLuint numTextureBarriers, + const GLuint *textures, + const GLenum *dstLayouts) +{ + +} + +void GLAPIENTRY +_mesa_ImportMemoryFdEXT(GLuint memory, + GLuint64 size, + GLenum handleType, + GLint fd) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.EXT_memory_object_fd) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glImportMemoryFdEXT(unsupported)"); + return; + } + + if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) { + _mesa_error(ctx, GL_INVALID_VALUE, "glImportMemoryFdEXT(handleType=%u)", + handleType); + return; + } + + struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory); + if (!memObj) + return; + + ctx->Driver.ImportMemoryObjectFd(ctx, memObj, size, fd); + memObj->Immutable = GL_TRUE; +} + +void GLAPIENTRY +_mesa_ImportSemaphoreFdEXT(GLuint semaphore, + GLenum handleType, + GLint fd) +{ + +} diff --git a/lib/mesa/src/mesa/main/externalobjects.h b/lib/mesa/src/mesa/main/externalobjects.h new file mode 100644 index 000000000..a9a12b821 --- /dev/null +++ b/lib/mesa/src/mesa/main/externalobjects.h @@ -0,0 +1,231 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2017 Red Hat. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: Dave Airlie <airlied@gmail.com> + * Andres Rodriguez <andresx7@gmail.com> + */ + +/** + * \file externalobjects.h + * + * Declarations of functions related to the API interop extensions. + */ + +#ifndef EXTERNALOBJECTS_H +#define EXTERNALOBJECTS_H + +#include "glheader.h" +#include "hash.h" + +static inline struct gl_memory_object * +_mesa_lookup_memory_object(struct gl_context *ctx, GLuint memory) +{ + if (!memory) + return NULL; + + return (struct gl_memory_object *) + _mesa_HashLookup(ctx->Shared->MemoryObjects, memory); +} + +static inline struct gl_memory_object * +_mesa_lookup_memory_object_locked(struct gl_context *ctx, GLuint memory) +{ + if (!memory) + return NULL; + + return (struct gl_memory_object *) + _mesa_HashLookupLocked(ctx->Shared->MemoryObjects, memory); +} + +extern void +_mesa_init_memory_object_functions(struct dd_function_table *driver); + +extern void +_mesa_initialize_memory_object(struct gl_context *ctx, + struct gl_memory_object *obj, + GLuint name); +extern void +_mesa_delete_memory_object(struct gl_context *ctx, struct gl_memory_object *mo); + +extern void GLAPIENTRY +_mesa_DeleteMemoryObjectsEXT(GLsizei n, const GLuint *memoryObjects); + +extern GLboolean GLAPIENTRY +_mesa_IsMemoryObjectEXT(GLuint memoryObject); + +extern void GLAPIENTRY +_mesa_CreateMemoryObjectsEXT(GLsizei n, GLuint *memoryObjects); + +extern void GLAPIENTRY +_mesa_MemoryObjectParameterivEXT(GLuint memoryObject, + GLenum pname, + const GLint *params); + +extern void GLAPIENTRY +_mesa_GetMemoryObjectParameterivEXT(GLuint memoryObject, + GLenum pname, + GLint *params); + +extern void GLAPIENTRY +_mesa_TexStorageMem2DEXT(GLenum target, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TexStorageMem2DMultisampleEXT(GLenum target, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLboolean fixedSampleLocations, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TexStorageMem3DEXT(GLenum target, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TexStorageMem3DMultisampleEXT(GLenum target, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLboolean fixedSampleLocations, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TextureStorageMem2DEXT(GLuint texture, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TextureStorageMem2DMultisampleEXT(GLuint texture, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLboolean fixedSampleLocations, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TextureStorageMem3DEXT(GLuint texture, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TextureStorageMem3DMultisampleEXT(GLuint texture, + GLsizei samples, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLboolean fixedSampleLocations, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TexStorageMem1DEXT(GLenum target, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_TextureStorageMem1DEXT(GLuint texture, + GLsizei levels, + GLenum internalFormat, + GLsizei width, + GLuint memory, + GLuint64 offset); + +extern void GLAPIENTRY +_mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores); + +extern void GLAPIENTRY +_mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores); + +extern GLboolean GLAPIENTRY +_mesa_IsSemaphoreEXT(GLuint semaphore); + +extern void GLAPIENTRY +_mesa_SemaphoreParameterui64vEXT(GLuint semaphore, + GLenum pname, + const GLuint64 *params); + +extern void GLAPIENTRY +_mesa_GetSemaphoreParameterui64vEXT(GLuint semaphore, + GLenum pname, + GLuint64 *params); + +extern void GLAPIENTRY +_mesa_WaitSemaphoreEXT(GLuint semaphore, + GLuint numBufferBarriers, + const GLuint *buffers, + GLuint numTextureBarriers, + const GLuint *textures, + const GLenum *srcLayouts); + +extern void GLAPIENTRY +_mesa_SignalSemaphoreEXT(GLuint semaphore, + GLuint numBufferBarriers, + const GLuint *buffers, + GLuint numTextureBarriers, + const GLuint *textures, + const GLenum *dstLayouts); + +extern void GLAPIENTRY +_mesa_ImportMemoryFdEXT(GLuint memory, + GLuint64 size, + GLenum handleType, + GLint fd); + +extern void GLAPIENTRY +_mesa_ImportSemaphoreFdEXT(GLuint semaphore, + GLenum handleType, + GLint fd); + +#endif diff --git a/lib/mesa/src/mesa/main/format_pack.c b/lib/mesa/src/mesa/main/format_pack.c index 3408081d4..f9e194d31 100644 --- a/lib/mesa/src/mesa/main/format_pack.c +++ b/lib/mesa/src/mesa/main/format_pack.c @@ -452,6 +452,30 @@ pack_ubyte_a1b5g5r5_unorm(const GLubyte src[4], void *dst) } static inline void +pack_ubyte_x1b5g5r5_unorm(const GLubyte src[4], void *dst) +{ + + + + uint8_t b = + _mesa_unorm_to_unorm(src[2], 8, 5); + + + uint8_t g = + _mesa_unorm_to_unorm(src[1], 8, 5); + + + uint8_t r = + _mesa_unorm_to_unorm(src[0], 8, 5); + + uint16_t d = 0; + d |= PACK(b, 1, 5); + d |= PACK(g, 6, 5); + d |= PACK(r, 11, 5); + (*(uint16_t *)dst) = d; +} + +static inline void pack_ubyte_b5g5r5a1_unorm(const GLubyte src[4], void *dst) { @@ -3635,7 +3659,7 @@ pack_ubyte_r11g11b10_float(const GLubyte src[4], void *dst) /* uint packing functions */ - + static inline void pack_uint_a8b8g8r8_uint(const GLuint src[4], void *dst) { @@ -5502,6 +5526,30 @@ pack_float_a1b5g5r5_unorm(const GLfloat src[4], void *dst) } static inline void +pack_float_x1b5g5r5_unorm(const GLfloat src[4], void *dst) +{ + + + + uint8_t b = + _mesa_float_to_unorm(src[2], 5); + + + uint8_t g = + _mesa_float_to_unorm(src[1], 5); + + + uint8_t r = + _mesa_float_to_unorm(src[0], 5); + + uint16_t d = 0; + d |= PACK(b, 1, 5); + d |= PACK(g, 6, 5); + d |= PACK(r, 11, 5); + (*(uint16_t *)dst) = d; +} + +static inline void pack_float_b5g5r5a1_unorm(const GLfloat src[4], void *dst) { @@ -7267,6 +7315,9 @@ _mesa_get_pack_ubyte_rgba_function(mesa_format format) case MESA_FORMAT_A1B5G5R5_UNORM: return pack_ubyte_a1b5g5r5_unorm; + case MESA_FORMAT_X1B5G5R5_UNORM: + return pack_ubyte_x1b5g5r5_unorm; + case MESA_FORMAT_B5G5R5A1_UNORM: return pack_ubyte_b5g5r5a1_unorm; @@ -7810,6 +7861,9 @@ _mesa_get_pack_float_rgba_function(mesa_format format) case MESA_FORMAT_A1B5G5R5_UNORM: return pack_float_a1b5g5r5_unorm; + case MESA_FORMAT_X1B5G5R5_UNORM: + return pack_float_x1b5g5r5_unorm; + case MESA_FORMAT_B5G5R5A1_UNORM: return pack_float_b5g5r5a1_unorm; @@ -8199,6 +8253,13 @@ _mesa_pack_ubyte_rgba_row(mesa_format format, GLuint n, } break; + case MESA_FORMAT_X1B5G5R5_UNORM: + for (i = 0; i < n; ++i) { + pack_ubyte_x1b5g5r5_unorm(src[i], d); + d += 2; + } + break; + case MESA_FORMAT_B5G5R5A1_UNORM: for (i = 0; i < n; ++i) { pack_ubyte_b5g5r5a1_unorm(src[i], d); @@ -9341,7 +9402,7 @@ _mesa_pack_uint_rgba_row(mesa_format format, GLuint n, GLubyte *d = dst; switch (format) { - + case MESA_FORMAT_A8B8G8R8_UINT: for (i = 0; i < n; ++i) { pack_uint_a8b8g8r8_uint(src[i], d); @@ -9988,6 +10049,13 @@ _mesa_pack_float_rgba_row(mesa_format format, GLuint n, } break; + case MESA_FORMAT_X1B5G5R5_UNORM: + for (i = 0; i < n; ++i) { + pack_float_x1b5g5r5_unorm(src[i], d); + d += 2; + } + break; + case MESA_FORMAT_B5G5R5A1_UNORM: for (i = 0; i < n; ++i) { pack_float_b5g5r5a1_unorm(src[i], d); diff --git a/lib/mesa/src/mesa/main/format_unpack.c b/lib/mesa/src/mesa/main/format_unpack.c index 760cbc267..21c55416b 100644 --- a/lib/mesa/src/mesa/main/format_unpack.c +++ b/lib/mesa/src/mesa/main/format_unpack.c @@ -403,6 +403,27 @@ unpack_float_a1b5g5r5_unorm(const void *void_src, GLfloat dst[4]) } static inline void +unpack_float_x1b5g5r5_unorm(const void *void_src, GLfloat dst[4]) +{ + uint16_t *src = (uint16_t *)void_src; + uint8_t b = UNPACK(*src, 1, 5); + uint8_t g = UNPACK(*src, 6, 5); + uint8_t r = UNPACK(*src, 11, 5); + + + + dst[0] = _mesa_unorm_to_float(r, 5); + + + dst[1] = _mesa_unorm_to_float(g, 5); + + + dst[2] = _mesa_unorm_to_float(b, 5); + + dst[3] = 1.0f; +} + +static inline void unpack_float_b5g5r5a1_unorm(const void *void_src, GLfloat dst[4]) { uint16_t *src = (uint16_t *)void_src; @@ -2582,6 +2603,27 @@ unpack_ubyte_a1b5g5r5_unorm(const void *void_src, GLubyte dst[4]) } static inline void +unpack_ubyte_x1b5g5r5_unorm(const void *void_src, GLubyte dst[4]) +{ + uint16_t *src = (uint16_t *)void_src; + uint8_t b = UNPACK(*src, 1, 5); + uint8_t g = UNPACK(*src, 6, 5); + uint8_t r = UNPACK(*src, 11, 5); + + + + dst[0] = _mesa_unorm_to_unorm(r, 5, 8); + + + dst[1] = _mesa_unorm_to_unorm(g, 5, 8); + + + dst[2] = _mesa_unorm_to_unorm(b, 5, 8); + + dst[3] = 255; +} + +static inline void unpack_ubyte_b5g5r5a1_unorm(const void *void_src, GLubyte dst[4]) { uint16_t *src = (uint16_t *)void_src; @@ -3989,7 +4031,7 @@ unpack_ubyte_bgr_srgb8(const void *void_src, GLubyte dst[4]) /* integer packing functions */ - + static inline void unpack_int_a8b8g8r8_uint(const void *void_src, GLuint dst[4]) { @@ -5389,6 +5431,12 @@ _mesa_unpack_rgba_row(mesa_format format, GLuint n, s += 2; } break; + case MESA_FORMAT_X1B5G5R5_UNORM: + for (i = 0; i < n; ++i) { + unpack_float_x1b5g5r5_unorm(s, dst[i]); + s += 2; + } + break; case MESA_FORMAT_B5G5R5A1_UNORM: for (i = 0; i < n; ++i) { unpack_float_b5g5r5a1_unorm(s, dst[i]); @@ -6045,6 +6093,13 @@ _mesa_unpack_ubyte_rgba_row(mesa_format format, GLuint n, } break; + case MESA_FORMAT_X1B5G5R5_UNORM: + for (i = 0; i < n; ++i) { + unpack_ubyte_x1b5g5r5_unorm(s, dst[i]); + s += 2; + } + break; + case MESA_FORMAT_B5G5R5A1_UNORM: for (i = 0; i < n; ++i) { unpack_ubyte_b5g5r5a1_unorm(s, dst[i]); @@ -6541,7 +6596,7 @@ _mesa_unpack_uint_rgba_row(mesa_format format, GLuint n, GLuint i; switch (format) { - + case MESA_FORMAT_A8B8G8R8_UINT: for (i = 0; i < n; ++i) { unpack_int_a8b8g8r8_uint(s, dst[i]); diff --git a/lib/mesa/src/mesa/main/format_utils.c b/lib/mesa/src/mesa/main/format_utils.c index d16d69c37..31580750b 100644 --- a/lib/mesa/src/mesa/main/format_utils.c +++ b/lib/mesa/src/mesa/main/format_utils.c @@ -312,6 +312,20 @@ _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t dst_stride, * enable it for specific combinations that are known to work. */ if (!rebase_swizzle) { + /* Do a direct memcpy where possible */ + if ((dst_format_is_mesa_array_format && + src_format_is_mesa_array_format && + src_array_format == dst_array_format) || + src_format == dst_format) { + int format_size = _mesa_get_format_bytes(src_format); + for (row = 0; row < height; row++) { + memcpy(dst, src, width * format_size); + src += src_stride; + dst += dst_stride; + } + return; + } + /* Handle the cases where we can directly unpack */ if (!src_format_is_mesa_array_format) { if (dst_array_format == RGBA32_FLOAT) { diff --git a/lib/mesa/src/mesa/main/formats.csv b/lib/mesa/src/mesa/main/formats.csv index 285921ed4..ce53f8f05 100644 --- a/lib/mesa/src/mesa/main/formats.csv +++ b/lib/mesa/src/mesa/main/formats.csv @@ -68,6 +68,7 @@ MESA_FORMAT_B4G4R4A4_UNORM , packed, 1, 1, 1, un4 , un4 , un4 , u MESA_FORMAT_B4G4R4X4_UNORM , packed, 1, 1, 1, un4 , un4 , un4 , x4 , zyx1, rgb MESA_FORMAT_A4R4G4B4_UNORM , packed, 1, 1, 1, un4 , un4 , un4 , un4 , yzwx, rgb MESA_FORMAT_A1B5G5R5_UNORM , packed, 1, 1, 1, un1 , un5 , un5 , un5 , wzyx, rgb +MESA_FORMAT_X1B5G5R5_UNORM , packed, 1, 1, 1, x1 , un5 , un5 , un5 , wzy1, rgb MESA_FORMAT_B5G5R5A1_UNORM , packed, 1, 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb MESA_FORMAT_B5G5R5X1_UNORM , packed, 1, 1, 1, un5 , un5 , un5 , x1 , zyx1, rgb MESA_FORMAT_A1R5G5B5_UNORM , packed, 1, 1, 1, un1 , un5 , un5 , un5 , yzwx, rgb diff --git a/lib/mesa/src/mesa/main/get.h b/lib/mesa/src/mesa/main/get.h index ce97cc586..34cb9381f 100644 --- a/lib/mesa/src/mesa/main/get.h +++ b/lib/mesa/src/mesa/main/get.h @@ -54,6 +54,9 @@ extern void GLAPIENTRY _mesa_GetFixedv(GLenum pname, GLfixed *params); extern void GLAPIENTRY +_mesa_GetUnsignedBytevEXT(GLenum pname, GLubyte *data); + +extern void GLAPIENTRY _mesa_GetBooleani_v( GLenum pname, GLuint index, GLboolean *params ); extern void GLAPIENTRY @@ -71,6 +74,9 @@ _mesa_GetFloati_v(GLenum target, GLuint index, GLfloat *data); extern void GLAPIENTRY _mesa_GetDoublei_v(GLenum target, GLuint index, GLdouble *data); +extern void GLAPIENTRY +_mesa_GetUnsignedBytei_vEXT(GLenum target, GLuint index, GLubyte *data); + extern const GLubyte * GLAPIENTRY _mesa_GetString( GLenum name ); diff --git a/lib/mesa/src/mesa/main/lines.h b/lib/mesa/src/mesa/main/lines.h index fa15e50ac..78a405cba 100644 --- a/lib/mesa/src/mesa/main/lines.h +++ b/lib/mesa/src/mesa/main/lines.h @@ -37,13 +37,16 @@ struct gl_context; +void GLAPIENTRY +_mesa_LineWidth_no_error(GLfloat width); + extern void GLAPIENTRY _mesa_LineWidth( GLfloat width ); extern void GLAPIENTRY _mesa_LineStipple( GLint factor, GLushort pattern ); -extern void GLAPIENTRY +extern void _mesa_init_line( struct gl_context * ctx ); #endif diff --git a/lib/mesa/src/mesa/main/multisample.h b/lib/mesa/src/mesa/main/multisample.h index 7441d3ee9..a7cd2918d 100644 --- a/lib/mesa/src/mesa/main/multisample.h +++ b/lib/mesa/src/mesa/main/multisample.h @@ -41,9 +41,15 @@ _mesa_init_multisample(struct gl_context *ctx); extern void GLAPIENTRY _mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat* val); +void GLAPIENTRY +_mesa_SampleMaski_no_error(GLuint index, GLbitfield mask); + extern void GLAPIENTRY _mesa_SampleMaski(GLuint index, GLbitfield mask); +void GLAPIENTRY +_mesa_MinSampleShading_no_error(GLclampf value); + extern void GLAPIENTRY _mesa_MinSampleShading(GLclampf value); diff --git a/lib/mesa/src/mesa/main/points.c b/lib/mesa/src/mesa/main/points.c index 2d62e73c1..095e2a3d7 100644 --- a/lib/mesa/src/mesa/main/points.c +++ b/lib/mesa/src/mesa/main/points.c @@ -40,18 +40,16 @@ * \param size point diameter in pixels * \sa glPointSize(). */ -void GLAPIENTRY -_mesa_PointSize( GLfloat size ) +static ALWAYS_INLINE void +point_size(struct gl_context *ctx, GLfloat size, bool no_error) { - GET_CURRENT_CONTEXT(ctx); - - if (size <= 0.0F) { - _mesa_error( ctx, GL_INVALID_VALUE, "glPointSize" ); + if (ctx->Point.Size == size) return; - } - if (ctx->Point.Size == size) + if (!no_error && size <= 0.0F) { + _mesa_error(ctx, GL_INVALID_VALUE, "glPointSize"); return; + } FLUSH_VERTICES(ctx, _NEW_POINT); ctx->Point.Size = size; @@ -62,6 +60,22 @@ _mesa_PointSize( GLfloat size ) void GLAPIENTRY +_mesa_PointSize_no_error(GLfloat size) +{ + GET_CURRENT_CONTEXT(ctx); + point_size(ctx, size, true); +} + + +void GLAPIENTRY +_mesa_PointSize( GLfloat size ) +{ + GET_CURRENT_CONTEXT(ctx); + point_size(ctx, size, false); +} + + +void GLAPIENTRY _mesa_PointParameteri( GLenum pname, GLint param ) { GLfloat p[3]; diff --git a/lib/mesa/src/mesa/main/points.h b/lib/mesa/src/mesa/main/points.h index c3d0f691b..c2b67a371 100644 --- a/lib/mesa/src/mesa/main/points.h +++ b/lib/mesa/src/mesa/main/points.h @@ -37,6 +37,9 @@ struct gl_context; +void GLAPIENTRY +_mesa_PointSize_no_error(GLfloat size); + extern void GLAPIENTRY _mesa_PointSize( GLfloat size ); diff --git a/lib/mesa/src/mesa/main/readpix.h b/lib/mesa/src/mesa/main/readpix.h index 481ad9d9c..eff8e0290 100644 --- a/lib/mesa/src/mesa/main/readpix.h +++ b/lib/mesa/src/mesa/main/readpix.h @@ -58,10 +58,19 @@ _mesa_readpixels(struct gl_context *ctx, const struct gl_pixelstore_attrib *packing, GLvoid *pixels); +void GLAPIENTRY +_mesa_ReadPixels_no_error(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels); + extern void GLAPIENTRY _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels ); +void GLAPIENTRY +_mesa_ReadnPixelsARB_no_error(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei bufSize, + GLvoid *pixels); + extern void GLAPIENTRY _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, diff --git a/lib/mesa/src/mesa/main/texcompress_s3tc.c b/lib/mesa/src/mesa/main/texcompress_s3tc.c index 992ad058b..1c6cbba89 100644 --- a/lib/mesa/src/mesa/main/texcompress_s3tc.c +++ b/lib/mesa/src/mesa/main/texcompress_s3tc.c @@ -31,91 +31,17 @@ #include "glheader.h" #include "imports.h" -#include "dlopen.h" #include "image.h" #include "macros.h" #include "mtypes.h" #include "texcompress.h" #include "texcompress_s3tc.h" +#include "texcompress_s3tc_tmp.h" #include "texstore.h" #include "format_unpack.h" #include "util/format_srgb.h" -#if defined(_WIN32) || defined(WIN32) -#define DXTN_LIBNAME "dxtn.dll" -#define RTLD_LAZY 0 -#define RTLD_GLOBAL 0 -#elif defined(__CYGWIN__) -#define DXTN_LIBNAME "cygtxc_dxtn.dll" -#else -#define DXTN_LIBNAME "libtxc_dxtn.so" -#endif - -typedef void (*dxtFetchTexelFuncExt)( GLint srcRowstride, const GLubyte *pixdata, GLint col, GLint row, GLvoid *texelOut ); - -static dxtFetchTexelFuncExt fetch_ext_rgb_dxt1 = NULL; -static dxtFetchTexelFuncExt fetch_ext_rgba_dxt1 = NULL; -static dxtFetchTexelFuncExt fetch_ext_rgba_dxt3 = NULL; -static dxtFetchTexelFuncExt fetch_ext_rgba_dxt5 = NULL; - -typedef void (*dxtCompressTexFuncExt)(GLint srccomps, GLint width, - GLint height, const GLubyte *srcPixData, - GLenum destformat, GLubyte *dest, - GLint dstRowStride); - -static dxtCompressTexFuncExt ext_tx_compress_dxtn = NULL; - -static void *dxtlibhandle = NULL; - - -void -_mesa_init_texture_s3tc( struct gl_context *ctx ) -{ - /* called during context initialization */ - ctx->Mesa_DXTn = GL_FALSE; - if (!dxtlibhandle) { - dxtlibhandle = _mesa_dlopen(DXTN_LIBNAME, 0); - if (!dxtlibhandle) { - _mesa_warning(ctx, "couldn't open " DXTN_LIBNAME ", software DXTn " - "compression/decompression unavailable"); - } - else { - /* the fetch functions are not per context! Might be problematic... */ - fetch_ext_rgb_dxt1 = (dxtFetchTexelFuncExt) - _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgb_dxt1"); - fetch_ext_rgba_dxt1 = (dxtFetchTexelFuncExt) - _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt1"); - fetch_ext_rgba_dxt3 = (dxtFetchTexelFuncExt) - _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt3"); - fetch_ext_rgba_dxt5 = (dxtFetchTexelFuncExt) - _mesa_dlsym(dxtlibhandle, "fetch_2d_texel_rgba_dxt5"); - ext_tx_compress_dxtn = (dxtCompressTexFuncExt) - _mesa_dlsym(dxtlibhandle, "tx_compress_dxtn"); - - if (!fetch_ext_rgb_dxt1 || - !fetch_ext_rgba_dxt1 || - !fetch_ext_rgba_dxt3 || - !fetch_ext_rgba_dxt5 || - !ext_tx_compress_dxtn) { - _mesa_warning(ctx, "couldn't reference all symbols in " - DXTN_LIBNAME ", software DXTn compression/decompression " - "unavailable"); - fetch_ext_rgb_dxt1 = NULL; - fetch_ext_rgba_dxt1 = NULL; - fetch_ext_rgba_dxt3 = NULL; - fetch_ext_rgba_dxt5 = NULL; - ext_tx_compress_dxtn = NULL; - _mesa_dlclose(dxtlibhandle); - dxtlibhandle = NULL; - } - } - } - if (dxtlibhandle) { - ctx->Mesa_DXTn = GL_TRUE; - } -} - /** * Store user's image in rgb_dxt1 format. */ @@ -158,14 +84,9 @@ _mesa_texstore_rgb_dxt1(TEXSTORE_PARAMS) dst = dstSlices[0]; - if (ext_tx_compress_dxtn) { - (*ext_tx_compress_dxtn)(3, srcWidth, srcHeight, pixels, - GL_COMPRESSED_RGB_S3TC_DXT1_EXT, - dst, dstRowStride); - } - else { - _mesa_warning(ctx, "external dxt library not available: texstore_rgb_dxt1"); - } + tx_compress_dxtn(3, srcWidth, srcHeight, pixels, + GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + dst, dstRowStride); free((void *) tempImage); @@ -216,14 +137,9 @@ _mesa_texstore_rgba_dxt1(TEXSTORE_PARAMS) dst = dstSlices[0]; - if (ext_tx_compress_dxtn) { - (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, - GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, - dst, dstRowStride); - } - else { - _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt1"); - } + tx_compress_dxtn(4, srcWidth, srcHeight, pixels, + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + dst, dstRowStride); free((void*) tempImage); @@ -273,14 +189,9 @@ _mesa_texstore_rgba_dxt3(TEXSTORE_PARAMS) dst = dstSlices[0]; - if (ext_tx_compress_dxtn) { - (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, - GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, - dst, dstRowStride); - } - else { - _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt3"); - } + tx_compress_dxtn(4, srcWidth, srcHeight, pixels, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, + dst, dstRowStride); free((void *) tempImage); @@ -330,14 +241,9 @@ _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS) dst = dstSlices[0]; - if (ext_tx_compress_dxtn) { - (*ext_tx_compress_dxtn)(4, srcWidth, srcHeight, pixels, - GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, - dst, dstRowStride); - } - else { - _mesa_warning(ctx, "external dxt library not available: texstore_rgba_dxt5"); - } + tx_compress_dxtn(4, srcWidth, srcHeight, pixels, + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, + dst, dstRowStride); free((void *) tempImage); @@ -345,85 +251,52 @@ _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS) } -/** Report problem with dxt texture decompression, once */ -static void -problem(const char *func) -{ - static GLboolean warned = GL_FALSE; - if (!warned) { - _mesa_debug(NULL, "attempted to decode DXT texture without " - "library available: %s\n", func); - warned = GL_TRUE; - } -} - - static void fetch_rgb_dxt1(const GLubyte *map, GLint rowStride, GLint i, GLint j, GLfloat *texel) { - if (fetch_ext_rgb_dxt1) { - GLubyte tex[4]; - fetch_ext_rgb_dxt1(rowStride, map, i, j, tex); - texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); - } - else { - problem("rgb_dxt1"); - } + GLubyte tex[4]; + fetch_2d_texel_rgb_dxt1(rowStride, map, i, j, tex); + texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } static void fetch_rgba_dxt1(const GLubyte *map, GLint rowStride, GLint i, GLint j, GLfloat *texel) { - if (fetch_ext_rgba_dxt1) { - GLubyte tex[4]; - fetch_ext_rgba_dxt1(rowStride, map, i, j, tex); - texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); - } - else { - problem("rgba_dxt1"); - } + GLubyte tex[4]; + fetch_2d_texel_rgba_dxt1(rowStride, map, i, j, tex); + texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } static void fetch_rgba_dxt3(const GLubyte *map, GLint rowStride, GLint i, GLint j, GLfloat *texel) { - if (fetch_ext_rgba_dxt3) { - GLubyte tex[4]; - fetch_ext_rgba_dxt3(rowStride, map, i, j, tex); - texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); - } - else { - problem("rgba_dxt3"); - } + GLubyte tex[4]; + fetch_2d_texel_rgba_dxt3(rowStride, map, i, j, tex); + texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } static void fetch_rgba_dxt5(const GLubyte *map, GLint rowStride, GLint i, GLint j, GLfloat *texel) { - if (fetch_ext_rgba_dxt5) { - GLubyte tex[4]; - fetch_ext_rgba_dxt5(rowStride, map, i, j, tex); - texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); - texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); - texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); - } - else { - problem("rgba_dxt5"); - } + GLubyte tex[4]; + fetch_2d_texel_rgba_dxt5(rowStride, map, i, j, tex); + texel[RCOMP] = UBYTE_TO_FLOAT(tex[RCOMP]); + texel[GCOMP] = UBYTE_TO_FLOAT(tex[GCOMP]); + texel[BCOMP] = UBYTE_TO_FLOAT(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } @@ -431,68 +304,48 @@ static void fetch_srgb_dxt1(const GLubyte *map, GLint rowStride, GLint i, GLint j, GLfloat *texel) { - if (fetch_ext_rgb_dxt1) { - GLubyte tex[4]; - fetch_ext_rgb_dxt1(rowStride, map, i, j, tex); - texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); - texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); - texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); - } - else { - problem("srgb_dxt1"); - } + GLubyte tex[4]; + fetch_2d_texel_rgb_dxt1(rowStride, map, i, j, tex); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } static void fetch_srgba_dxt1(const GLubyte *map, GLint rowStride, GLint i, GLint j, GLfloat *texel) { - if (fetch_ext_rgba_dxt1) { - GLubyte tex[4]; - fetch_ext_rgba_dxt1(rowStride, map, i, j, tex); - texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); - texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); - texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); - } - else { - problem("srgba_dxt1"); - } + GLubyte tex[4]; + fetch_2d_texel_rgba_dxt1(rowStride, map, i, j, tex); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } static void fetch_srgba_dxt3(const GLubyte *map, GLint rowStride, GLint i, GLint j, GLfloat *texel) { - if (fetch_ext_rgba_dxt3) { - GLubyte tex[4]; - fetch_ext_rgba_dxt3(rowStride, map, i, j, tex); - texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); - texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); - texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); - } - else { - problem("srgba_dxt3"); - } + GLubyte tex[4]; + fetch_2d_texel_rgba_dxt3(rowStride, map, i, j, tex); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } static void fetch_srgba_dxt5(const GLubyte *map, GLint rowStride, GLint i, GLint j, GLfloat *texel) { - if (fetch_ext_rgba_dxt5) { - GLubyte tex[4]; - fetch_ext_rgba_dxt5(rowStride, map, i, j, tex); - texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); - texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); - texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); - texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); - } - else { - problem("srgba_dxt5"); - } + GLubyte tex[4]; + fetch_2d_texel_rgba_dxt5(rowStride, map, i, j, tex); + texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(tex[RCOMP]); + texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(tex[GCOMP]); + texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(tex[BCOMP]); + texel[ACOMP] = UBYTE_TO_FLOAT(tex[ACOMP]); } diff --git a/lib/mesa/src/mesa/main/texcompress_s3tc.h b/lib/mesa/src/mesa/main/texcompress_s3tc.h index 438b71fe3..0dbb5fc53 100644 --- a/lib/mesa/src/mesa/main/texcompress_s3tc.h +++ b/lib/mesa/src/mesa/main/texcompress_s3tc.h @@ -44,9 +44,6 @@ extern GLboolean _mesa_texstore_rgba_dxt5(TEXSTORE_PARAMS); -extern void -_mesa_init_texture_s3tc(struct gl_context *ctx); - extern compressed_fetch_func _mesa_get_dxt_fetch_func(mesa_format format); diff --git a/lib/mesa/src/mesa/main/texcompress_s3tc_tmp.h b/lib/mesa/src/mesa/main/texcompress_s3tc_tmp.h new file mode 100644 index 000000000..61630f247 --- /dev/null +++ b/lib/mesa/src/mesa/main/texcompress_s3tc_tmp.h @@ -0,0 +1,989 @@ +/* + * libtxc_dxtn + * Version: 1.0 + * + * Copyright (C) 2004 Roland Scheidegger All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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. + */ + +#ifdef __APPLE__ +#include <OpenGL/gl.h> +#else +#include <GL/gl.h> +#endif + +typedef GLubyte GLchan; +#define UBYTE_TO_CHAN(b) (b) +#define CHAN_MAX 255 +#define RCOMP 0 +#define GCOMP 1 +#define BCOMP 2 +#define ACOMP 3 + +#define EXP5TO8R(packedcol) \ + ((((packedcol) >> 8) & 0xf8) | (((packedcol) >> 13) & 0x7)) + +#define EXP6TO8G(packedcol) \ + ((((packedcol) >> 3) & 0xfc) | (((packedcol) >> 9) & 0x3)) + +#define EXP5TO8B(packedcol) \ + ((((packedcol) << 3) & 0xf8) | (((packedcol) >> 2) & 0x7)) + +#define EXP4TO8(col) \ + ((col) | ((col) << 4)) + +/* inefficient. To be efficient, it would be necessary to decode 16 pixels at once */ + +static void dxt135_decode_imageblock ( const GLubyte *img_block_src, + GLint i, GLint j, GLuint dxt_type, GLvoid *texel ) { + GLchan *rgba = (GLchan *) texel; + const GLushort color0 = img_block_src[0] | (img_block_src[1] << 8); + const GLushort color1 = img_block_src[2] | (img_block_src[3] << 8); + const GLuint bits = img_block_src[4] | (img_block_src[5] << 8) | + (img_block_src[6] << 16) | (img_block_src[7] << 24); + /* What about big/little endian? */ + GLubyte bit_pos = 2 * (j * 4 + i) ; + GLubyte code = (GLubyte) ((bits >> bit_pos) & 3); + + rgba[ACOMP] = CHAN_MAX; + switch (code) { + case 0: + rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color0) ); + rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color0) ); + rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color0) ); + break; + case 1: + rgba[RCOMP] = UBYTE_TO_CHAN( EXP5TO8R(color1) ); + rgba[GCOMP] = UBYTE_TO_CHAN( EXP6TO8G(color1) ); + rgba[BCOMP] = UBYTE_TO_CHAN( EXP5TO8B(color1) ); + break; + case 2: + if ((dxt_type > 1) || (color0 > color1)) { + rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) * 2 + EXP5TO8R(color1)) / 3) ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) * 2 + EXP6TO8G(color1)) / 3) ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) * 2 + EXP5TO8B(color1)) / 3) ); + } + else { + rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1)) / 2) ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1)) / 2) ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1)) / 2) ); + } + break; + case 3: + if ((dxt_type > 1) || (color0 > color1)) { + rgba[RCOMP] = UBYTE_TO_CHAN( ((EXP5TO8R(color0) + EXP5TO8R(color1) * 2) / 3) ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((EXP6TO8G(color0) + EXP6TO8G(color1) * 2) / 3) ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((EXP5TO8B(color0) + EXP5TO8B(color1) * 2) / 3) ); + } + else { + rgba[RCOMP] = 0; + rgba[GCOMP] = 0; + rgba[BCOMP] = 0; + if (dxt_type == 1) rgba[ACOMP] = UBYTE_TO_CHAN(0); + } + break; + default: + /* CANNOT happen (I hope) */ + break; + } +} + + +static void fetch_2d_texel_rgb_dxt1(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel) +{ + /* Extract the (i,j) pixel from pixdata and return it + * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. + */ + + const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8); + dxt135_decode_imageblock(blksrc, (i&3), (j&3), 0, texel); +} + + +static void fetch_2d_texel_rgba_dxt1(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel) +{ + /* Extract the (i,j) pixel from pixdata and return it + * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. + */ + + const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8); + dxt135_decode_imageblock(blksrc, (i&3), (j&3), 1, texel); +} + +static void fetch_2d_texel_rgba_dxt3(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel) { + + /* Extract the (i,j) pixel from pixdata and return it + * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. + */ + + GLchan *rgba = (GLchan *) texel; + const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16); + const GLubyte anibble = (blksrc[((j&3) * 4 + (i&3)) / 2] >> (4 * (i&1))) & 0xf; + dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); + rgba[ACOMP] = UBYTE_TO_CHAN( (GLubyte)(EXP4TO8(anibble)) ); +} + +static void fetch_2d_texel_rgba_dxt5(GLint srcRowStride, const GLubyte *pixdata, + GLint i, GLint j, GLvoid *texel) { + + /* Extract the (i,j) pixel from pixdata and return it + * in texel[RCOMP], texel[GCOMP], texel[BCOMP], texel[ACOMP]. + */ + + GLchan *rgba = (GLchan *) texel; + const GLubyte *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 16); + const GLubyte alpha0 = blksrc[0]; + const GLubyte alpha1 = blksrc[1]; + const GLubyte bit_pos = ((j&3) * 4 + (i&3)) * 3; + const GLubyte acodelow = blksrc[2 + bit_pos / 8]; + const GLubyte acodehigh = blksrc[3 + bit_pos / 8]; + const GLubyte code = (acodelow >> (bit_pos & 0x7) | + (acodehigh << (8 - (bit_pos & 0x7)))) & 0x7; + dxt135_decode_imageblock(blksrc + 8, (i&3), (j&3), 2, texel); + if (code == 0) + rgba[ACOMP] = UBYTE_TO_CHAN( alpha0 ); + else if (code == 1) + rgba[ACOMP] = UBYTE_TO_CHAN( alpha1 ); + else if (alpha0 > alpha1) + rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7) ); + else if (code < 6) + rgba[ACOMP] = UBYTE_TO_CHAN( ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5) ); + else if (code == 6) + rgba[ACOMP] = 0; + else + rgba[ACOMP] = CHAN_MAX; +} + + +/* weights used for error function, basically weights (unsquared 2/4/1) according to rgb->luminance conversion + not sure if this really reflects visual perception */ +#define REDWEIGHT 4 +#define GREENWEIGHT 16 +#define BLUEWEIGHT 1 + +#define ALPHACUT 127 + +static void fancybasecolorsearch( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2], + GLint numxpixels, GLint numypixels, GLint type, GLboolean haveAlpha) +{ + /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */ + + /* TODO could also try to find a better encoding for the 3-color-encoding type, this really should be done + if it's rgba_dxt1 and we have alpha in the block, currently even values which will be mapped to black + due to their alpha value will influence the result */ + GLint i, j, colors, z; + GLuint pixerror, pixerrorred, pixerrorgreen, pixerrorblue, pixerrorbest; + GLint colordist, blockerrlin[2][3]; + GLubyte nrcolor[2]; + GLint pixerrorcolorbest[3]; + GLubyte enc = 0; + GLubyte cv[4][4]; + GLubyte testcolor[2][3]; + +/* fprintf(stderr, "color begin 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n", + bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/ + if (((bestcolor[0][0] & 0xf8) << 8 | (bestcolor[0][1] & 0xfc) << 3 | bestcolor[0][2] >> 3) < + ((bestcolor[1][0] & 0xf8) << 8 | (bestcolor[1][1] & 0xfc) << 3 | bestcolor[1][2] >> 3)) { + testcolor[0][0] = bestcolor[0][0]; + testcolor[0][1] = bestcolor[0][1]; + testcolor[0][2] = bestcolor[0][2]; + testcolor[1][0] = bestcolor[1][0]; + testcolor[1][1] = bestcolor[1][1]; + testcolor[1][2] = bestcolor[1][2]; + } + else { + testcolor[1][0] = bestcolor[0][0]; + testcolor[1][1] = bestcolor[0][1]; + testcolor[1][2] = bestcolor[0][2]; + testcolor[0][0] = bestcolor[1][0]; + testcolor[0][1] = bestcolor[1][1]; + testcolor[0][2] = bestcolor[1][2]; + } + + for (i = 0; i < 3; i ++) { + cv[0][i] = testcolor[0][i]; + cv[1][i] = testcolor[1][i]; + cv[2][i] = (testcolor[0][i] * 2 + testcolor[1][i]) / 3; + cv[3][i] = (testcolor[0][i] + testcolor[1][i] * 2) / 3; + } + + blockerrlin[0][0] = 0; + blockerrlin[0][1] = 0; + blockerrlin[0][2] = 0; + blockerrlin[1][0] = 0; + blockerrlin[1][1] = 0; + blockerrlin[1][2] = 0; + + nrcolor[0] = 0; + nrcolor[1] = 0; + + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + pixerrorbest = 0xffffffff; + for (colors = 0; colors < 4; colors++) { + colordist = srccolors[j][i][0] - (cv[colors][0]); + pixerror = colordist * colordist * REDWEIGHT; + pixerrorred = colordist; + colordist = srccolors[j][i][1] - (cv[colors][1]); + pixerror += colordist * colordist * GREENWEIGHT; + pixerrorgreen = colordist; + colordist = srccolors[j][i][2] - (cv[colors][2]); + pixerror += colordist * colordist * BLUEWEIGHT; + pixerrorblue = colordist; + if (pixerror < pixerrorbest) { + enc = colors; + pixerrorbest = pixerror; + pixerrorcolorbest[0] = pixerrorred; + pixerrorcolorbest[1] = pixerrorgreen; + pixerrorcolorbest[2] = pixerrorblue; + } + } + if (enc == 0) { + for (z = 0; z < 3; z++) { + blockerrlin[0][z] += 3 * pixerrorcolorbest[z]; + } + nrcolor[0] += 3; + } + else if (enc == 2) { + for (z = 0; z < 3; z++) { + blockerrlin[0][z] += 2 * pixerrorcolorbest[z]; + } + nrcolor[0] += 2; + for (z = 0; z < 3; z++) { + blockerrlin[1][z] += 1 * pixerrorcolorbest[z]; + } + nrcolor[1] += 1; + } + else if (enc == 3) { + for (z = 0; z < 3; z++) { + blockerrlin[0][z] += 1 * pixerrorcolorbest[z]; + } + nrcolor[0] += 1; + for (z = 0; z < 3; z++) { + blockerrlin[1][z] += 2 * pixerrorcolorbest[z]; + } + nrcolor[1] += 2; + } + else if (enc == 1) { + for (z = 0; z < 3; z++) { + blockerrlin[1][z] += 3 * pixerrorcolorbest[z]; + } + nrcolor[1] += 3; + } + } + } + if (nrcolor[0] == 0) nrcolor[0] = 1; + if (nrcolor[1] == 0) nrcolor[1] = 1; + for (j = 0; j < 2; j++) { + for (i = 0; i < 3; i++) { + GLint newvalue = testcolor[j][i] + blockerrlin[j][i] / nrcolor[j]; + if (newvalue <= 0) + testcolor[j][i] = 0; + else if (newvalue >= 255) + testcolor[j][i] = 255; + else testcolor[j][i] = newvalue; + } + } + + if ((abs(testcolor[0][0] - testcolor[1][0]) < 8) && + (abs(testcolor[0][1] - testcolor[1][1]) < 4) && + (abs(testcolor[0][2] - testcolor[1][2]) < 8)) { + /* both colors are so close they might get encoded as the same 16bit values */ + GLubyte coldiffred, coldiffgreen, coldiffblue, coldiffmax, factor, ind0, ind1; + + coldiffred = abs(testcolor[0][0] - testcolor[1][0]); + coldiffgreen = 2 * abs(testcolor[0][1] - testcolor[1][1]); + coldiffblue = abs(testcolor[0][2] - testcolor[1][2]); + coldiffmax = coldiffred; + if (coldiffmax < coldiffgreen) coldiffmax = coldiffgreen; + if (coldiffmax < coldiffblue) coldiffmax = coldiffblue; + if (coldiffmax > 0) { + if (coldiffmax > 4) factor = 2; + else if (coldiffmax > 2) factor = 3; + else factor = 4; + /* Won't do much if the color value is near 255... */ + /* argh so many ifs */ + if (testcolor[1][1] >= testcolor[0][1]) { + ind1 = 1; ind0 = 0; + } + else { + ind1 = 0; ind0 = 1; + } + if ((testcolor[ind1][1] + factor * coldiffgreen) <= 255) + testcolor[ind1][1] += factor * coldiffgreen; + else testcolor[ind1][1] = 255; + if ((testcolor[ind1][0] - testcolor[ind0][1]) > 0) { + if ((testcolor[ind1][0] + factor * coldiffred) <= 255) + testcolor[ind1][0] += factor * coldiffred; + else testcolor[ind1][0] = 255; + } + else { + if ((testcolor[ind0][0] + factor * coldiffred) <= 255) + testcolor[ind0][0] += factor * coldiffred; + else testcolor[ind0][0] = 255; + } + if ((testcolor[ind1][2] - testcolor[ind0][2]) > 0) { + if ((testcolor[ind1][2] + factor * coldiffblue) <= 255) + testcolor[ind1][2] += factor * coldiffblue; + else testcolor[ind1][2] = 255; + } + else { + if ((testcolor[ind0][2] + factor * coldiffblue) <= 255) + testcolor[ind0][2] += factor * coldiffblue; + else testcolor[ind0][2] = 255; + } + } + } + + if (((testcolor[0][0] & 0xf8) << 8 | (testcolor[0][1] & 0xfc) << 3 | testcolor[0][2] >> 3) < + ((testcolor[1][0] & 0xf8) << 8 | (testcolor[1][1] & 0xfc) << 3 | testcolor[1][2]) >> 3) { + for (i = 0; i < 3; i++) { + bestcolor[0][i] = testcolor[0][i]; + bestcolor[1][i] = testcolor[1][i]; + } + } + else { + for (i = 0; i < 3; i++) { + bestcolor[0][i] = testcolor[1][i]; + bestcolor[1][i] = testcolor[0][i]; + } + } + +/* fprintf(stderr, "color end 0 r/g/b %d/%d/%d, 1 r/g/b %d/%d/%d\n", + bestcolor[0][0], bestcolor[0][1], bestcolor[0][2], bestcolor[1][0], bestcolor[1][1], bestcolor[1][2]);*/ +} + + + +static void storedxtencodedblock( GLubyte *blkaddr, GLubyte srccolors[4][4][4], GLubyte *bestcolor[2], + GLint numxpixels, GLint numypixels, GLuint type, GLboolean haveAlpha) +{ + /* use same luminance-weighted distance metric to determine encoding as for finding the base colors */ + + GLint i, j, colors; + GLuint testerror, testerror2, pixerror, pixerrorbest; + GLint colordist; + GLushort color0, color1, tempcolor; + GLuint bits = 0, bits2 = 0; + GLubyte *colorptr; + GLubyte enc = 0; + GLubyte cv[4][4]; + + bestcolor[0][0] = bestcolor[0][0] & 0xf8; + bestcolor[0][1] = bestcolor[0][1] & 0xfc; + bestcolor[0][2] = bestcolor[0][2] & 0xf8; + bestcolor[1][0] = bestcolor[1][0] & 0xf8; + bestcolor[1][1] = bestcolor[1][1] & 0xfc; + bestcolor[1][2] = bestcolor[1][2] & 0xf8; + + color0 = bestcolor[0][0] << 8 | bestcolor[0][1] << 3 | bestcolor[0][2] >> 3; + color1 = bestcolor[1][0] << 8 | bestcolor[1][1] << 3 | bestcolor[1][2] >> 3; + if (color0 < color1) { + tempcolor = color0; color0 = color1; color1 = tempcolor; + colorptr = bestcolor[0]; bestcolor[0] = bestcolor[1]; bestcolor[1] = colorptr; + } + + + for (i = 0; i < 3; i++) { + cv[0][i] = bestcolor[0][i]; + cv[1][i] = bestcolor[1][i]; + cv[2][i] = (bestcolor[0][i] * 2 + bestcolor[1][i]) / 3; + cv[3][i] = (bestcolor[0][i] + bestcolor[1][i] * 2) / 3; + } + + testerror = 0; + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + pixerrorbest = 0xffffffff; + for (colors = 0; colors < 4; colors++) { + colordist = srccolors[j][i][0] - cv[colors][0]; + pixerror = colordist * colordist * REDWEIGHT; + colordist = srccolors[j][i][1] - cv[colors][1]; + pixerror += colordist * colordist * GREENWEIGHT; + colordist = srccolors[j][i][2] - cv[colors][2]; + pixerror += colordist * colordist * BLUEWEIGHT; + if (pixerror < pixerrorbest) { + pixerrorbest = pixerror; + enc = colors; + } + } + testerror += pixerrorbest; + bits |= enc << (2 * (j * 4 + i)); + } + } + /* some hw might disagree but actually decoding should always use 4-color encoding + for non-dxt1 formats */ + if (type == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { + for (i = 0; i < 3; i++) { + cv[2][i] = (bestcolor[0][i] + bestcolor[1][i]) / 2; + /* this isn't used. Looks like the black color constant can only be used + with RGB_DXT1 if I read the spec correctly (note though that the radeon gpu disagrees, + it will decode 3 to black even with DXT3/5), and due to how the color searching works + it won't get used even then */ + cv[3][i] = 0; + } + testerror2 = 0; + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + pixerrorbest = 0xffffffff; + if ((type == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) && (srccolors[j][i][3] <= ALPHACUT)) { + enc = 3; + pixerrorbest = 0; /* don't calculate error */ + } + else { + /* we're calculating the same what we have done already for colors 0-1 above... */ + for (colors = 0; colors < 3; colors++) { + colordist = srccolors[j][i][0] - cv[colors][0]; + pixerror = colordist * colordist * REDWEIGHT; + colordist = srccolors[j][i][1] - cv[colors][1]; + pixerror += colordist * colordist * GREENWEIGHT; + colordist = srccolors[j][i][2] - cv[colors][2]; + pixerror += colordist * colordist * BLUEWEIGHT; + if (pixerror < pixerrorbest) { + pixerrorbest = pixerror; + /* need to exchange colors later */ + if (colors > 1) enc = colors; + else enc = colors ^ 1; + } + } + } + testerror2 += pixerrorbest; + bits2 |= enc << (2 * (j * 4 + i)); + } + } + } else { + testerror2 = 0xffffffff; + } + + /* finally we're finished, write back colors and bits */ + if ((testerror > testerror2) || (haveAlpha)) { + *blkaddr++ = color1 & 0xff; + *blkaddr++ = color1 >> 8; + *blkaddr++ = color0 & 0xff; + *blkaddr++ = color0 >> 8; + *blkaddr++ = bits2 & 0xff; + *blkaddr++ = ( bits2 >> 8) & 0xff; + *blkaddr++ = ( bits2 >> 16) & 0xff; + *blkaddr = bits2 >> 24; + } + else { + *blkaddr++ = color0 & 0xff; + *blkaddr++ = color0 >> 8; + *blkaddr++ = color1 & 0xff; + *blkaddr++ = color1 >> 8; + *blkaddr++ = bits & 0xff; + *blkaddr++ = ( bits >> 8) & 0xff; + *blkaddr++ = ( bits >> 16) & 0xff; + *blkaddr = bits >> 24; + } +} + +static void encodedxtcolorblockfaster( GLubyte *blkaddr, GLubyte srccolors[4][4][4], + GLint numxpixels, GLint numypixels, GLuint type ) +{ +/* simplistic approach. We need two base colors, simply use the "highest" and the "lowest" color + present in the picture as base colors */ + + /* define lowest and highest color as shortest and longest vector to 0/0/0, though the + vectors are weighted similar to their importance in rgb-luminance conversion + doesn't work too well though... + This seems to be a rather difficult problem */ + + GLubyte *bestcolor[2]; + GLubyte basecolors[2][3]; + GLubyte i, j; + GLuint lowcv, highcv, testcv; + GLboolean haveAlpha = GL_FALSE; + + lowcv = highcv = srccolors[0][0][0] * srccolors[0][0][0] * REDWEIGHT + + srccolors[0][0][1] * srccolors[0][0][1] * GREENWEIGHT + + srccolors[0][0][2] * srccolors[0][0][2] * BLUEWEIGHT; + bestcolor[0] = bestcolor[1] = srccolors[0][0]; + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + /* don't use this as a base color if the pixel will get black/transparent anyway */ + if ((type != GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) || (srccolors[j][i][3] > ALPHACUT)) { + testcv = srccolors[j][i][0] * srccolors[j][i][0] * REDWEIGHT + + srccolors[j][i][1] * srccolors[j][i][1] * GREENWEIGHT + + srccolors[j][i][2] * srccolors[j][i][2] * BLUEWEIGHT; + if (testcv > highcv) { + highcv = testcv; + bestcolor[1] = srccolors[j][i]; + } + else if (testcv < lowcv) { + lowcv = testcv; + bestcolor[0] = srccolors[j][i]; + } + } + else haveAlpha = GL_TRUE; + } + } + /* make sure the original color values won't get touched... */ + for (j = 0; j < 2; j++) { + for (i = 0; i < 3; i++) { + basecolors[j][i] = bestcolor[j][i]; + } + } + bestcolor[0] = basecolors[0]; + bestcolor[1] = basecolors[1]; + + /* try to find better base colors */ + fancybasecolorsearch(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha); + /* find the best encoding for these colors, and store the result */ + storedxtencodedblock(blkaddr, srccolors, bestcolor, numxpixels, numypixels, type, haveAlpha); +} + +static void writedxt5encodedalphablock( GLubyte *blkaddr, GLubyte alphabase1, GLubyte alphabase2, + GLubyte alphaenc[16]) +{ + *blkaddr++ = alphabase1; + *blkaddr++ = alphabase2; + *blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6); + *blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7); + *blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5); + *blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6); + *blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7); + *blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5); +} + +static void encodedxt5alpha(GLubyte *blkaddr, GLubyte srccolors[4][4][4], + GLint numxpixels, GLint numypixels) +{ + GLubyte alphabase[2], alphause[2]; + GLshort alphatest[2]; + GLuint alphablockerror1, alphablockerror2, alphablockerror3; + GLubyte i, j, aindex, acutValues[7]; + GLubyte alphaenc1[16], alphaenc2[16], alphaenc3[16]; + GLboolean alphaabsmin = GL_FALSE; + GLboolean alphaabsmax = GL_FALSE; + GLshort alphadist; + + /* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */ + alphabase[0] = 0xff; alphabase[1] = 0x0; + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + if (srccolors[j][i][3] == 0) + alphaabsmin = GL_TRUE; + else if (srccolors[j][i][3] == 255) + alphaabsmax = GL_TRUE; + else { + if (srccolors[j][i][3] > alphabase[1]) + alphabase[1] = srccolors[j][i][3]; + if (srccolors[j][i][3] < alphabase[0]) + alphabase[0] = srccolors[j][i][3]; + } + } + } + + + if ((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax)) { /* one color, either max or min */ + /* shortcut here since it is a very common case (and also avoids later problems) */ + /* || (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax) */ + /* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */ + + *blkaddr++ = srccolors[0][0][3]; + blkaddr++; + *blkaddr++ = 0; + *blkaddr++ = 0; + *blkaddr++ = 0; + *blkaddr++ = 0; + *blkaddr++ = 0; + *blkaddr++ = 0; +/* fprintf(stderr, "enc0 used\n");*/ + return; + } + + /* find best encoding for alpha0 > alpha1 */ + /* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */ + alphablockerror1 = 0x0; + alphablockerror2 = 0xffffffff; + alphablockerror3 = 0xffffffff; + if (alphaabsmin) alphause[0] = 0; + else alphause[0] = alphabase[0]; + if (alphaabsmax) alphause[1] = 255; + else alphause[1] = alphabase[1]; + /* calculate the 7 cut values, just the middle between 2 of the computed alpha values */ + for (aindex = 0; aindex < 7; aindex++) { + /* don't forget here is always rounded down */ + acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14; + } + + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + /* maybe it's overkill to have the most complicated calculation just for the error + calculation which we only need to figure out if encoding1 or encoding2 is better... */ + if (srccolors[j][i][3] > acutValues[0]) { + alphaenc1[4*j + i] = 0; + alphadist = srccolors[j][i][3] - alphause[1]; + } + else if (srccolors[j][i][3] > acutValues[1]) { + alphaenc1[4*j + i] = 2; + alphadist = srccolors[j][i][3] - (alphause[1] * 6 + alphause[0] * 1) / 7; + } + else if (srccolors[j][i][3] > acutValues[2]) { + alphaenc1[4*j + i] = 3; + alphadist = srccolors[j][i][3] - (alphause[1] * 5 + alphause[0] * 2) / 7; + } + else if (srccolors[j][i][3] > acutValues[3]) { + alphaenc1[4*j + i] = 4; + alphadist = srccolors[j][i][3] - (alphause[1] * 4 + alphause[0] * 3) / 7; + } + else if (srccolors[j][i][3] > acutValues[4]) { + alphaenc1[4*j + i] = 5; + alphadist = srccolors[j][i][3] - (alphause[1] * 3 + alphause[0] * 4) / 7; + } + else if (srccolors[j][i][3] > acutValues[5]) { + alphaenc1[4*j + i] = 6; + alphadist = srccolors[j][i][3] - (alphause[1] * 2 + alphause[0] * 5) / 7; + } + else if (srccolors[j][i][3] > acutValues[6]) { + alphaenc1[4*j + i] = 7; + alphadist = srccolors[j][i][3] - (alphause[1] * 1 + alphause[0] * 6) / 7; + } + else { + alphaenc1[4*j + i] = 1; + alphadist = srccolors[j][i][3] - alphause[0]; + } + alphablockerror1 += alphadist * alphadist; + } + } +/* for (i = 0; i < 16; i++) { + fprintf(stderr, "%d ", alphaenc1[i]); + } + fprintf(stderr, "cutVals "); + for (i = 0; i < 8; i++) { + fprintf(stderr, "%d ", acutValues[i]); + } + fprintf(stderr, "srcVals "); + for (j = 0; j < numypixels; j++) + for (i = 0; i < numxpixels; i++) { + fprintf(stderr, "%d ", srccolors[j][i][3]); + } + + fprintf(stderr, "\n"); + }*/ + /* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax + are false but try it anyway */ + if (alphablockerror1 >= 32) { + + /* don't bother if encoding is already very good, this condition should also imply + we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */ + alphablockerror2 = 0; + for (aindex = 0; aindex < 5; aindex++) { + /* don't forget here is always rounded down */ + acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10; + } + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + /* maybe it's overkill to have the most complicated calculation just for the error + calculation which we only need to figure out if encoding1 or encoding2 is better... */ + if (srccolors[j][i][3] == 0) { + alphaenc2[4*j + i] = 6; + alphadist = 0; + } + else if (srccolors[j][i][3] == 255) { + alphaenc2[4*j + i] = 7; + alphadist = 0; + } + else if (srccolors[j][i][3] <= acutValues[0]) { + alphaenc2[4*j + i] = 0; + alphadist = srccolors[j][i][3] - alphabase[0]; + } + else if (srccolors[j][i][3] <= acutValues[1]) { + alphaenc2[4*j + i] = 2; + alphadist = srccolors[j][i][3] - (alphabase[0] * 4 + alphabase[1] * 1) / 5; + } + else if (srccolors[j][i][3] <= acutValues[2]) { + alphaenc2[4*j + i] = 3; + alphadist = srccolors[j][i][3] - (alphabase[0] * 3 + alphabase[1] * 2) / 5; + } + else if (srccolors[j][i][3] <= acutValues[3]) { + alphaenc2[4*j + i] = 4; + alphadist = srccolors[j][i][3] - (alphabase[0] * 2 + alphabase[1] * 3) / 5; + } + else if (srccolors[j][i][3] <= acutValues[4]) { + alphaenc2[4*j + i] = 5; + alphadist = srccolors[j][i][3] - (alphabase[0] * 1 + alphabase[1] * 4) / 5; + } + else { + alphaenc2[4*j + i] = 1; + alphadist = srccolors[j][i][3] - alphabase[1]; + } + alphablockerror2 += alphadist * alphadist; + } + } + + + /* skip this if the error is already very small + this encoding is MUCH better on average than #2 though, but expensive! */ + if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) { + GLshort blockerrlin1 = 0; + GLshort blockerrlin2 = 0; + GLubyte nralphainrangelow = 0; + GLubyte nralphainrangehigh = 0; + alphatest[0] = 0xff; + alphatest[1] = 0x0; + /* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */ + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + if ((srccolors[j][i][3] > alphatest[1]) && (srccolors[j][i][3] < (255 -(alphabase[1] - alphabase[0]) / 28))) + alphatest[1] = srccolors[j][i][3]; + if ((srccolors[j][i][3] < alphatest[0]) && (srccolors[j][i][3] > (alphabase[1] - alphabase[0]) / 28)) + alphatest[0] = srccolors[j][i][3]; + } + } + /* shouldn't happen too often, don't really care about those degenerated cases */ + if (alphatest[1] <= alphatest[0]) { + alphatest[0] = 1; + alphatest[1] = 254; +/* fprintf(stderr, "only 1 or 0 colors for encoding!\n");*/ + } + for (aindex = 0; aindex < 5; aindex++) { + /* don't forget here is always rounded down */ + acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10; + } + + /* find the "average" difference between the alpha values and the next encoded value. + This is then used to calculate new base values. + Should there be some weighting, i.e. those values closer to alphatest[x] have more weight, + since they will see more improvement, and also because the values in the middle are somewhat + likely to get no improvement at all (because the base values might move in different directions)? + OTOH it would mean the values in the middle are even less likely to get an improvement + */ + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + if (srccolors[j][i][3] <= alphatest[0] / 2) { + } + else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) { + } + else if (srccolors[j][i][3] <= acutValues[0]) { + blockerrlin1 += (srccolors[j][i][3] - alphatest[0]); + nralphainrangelow += 1; + } + else if (srccolors[j][i][3] <= acutValues[1]) { + blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5); + blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5); + nralphainrangelow += 1; + nralphainrangehigh += 1; + } + else if (srccolors[j][i][3] <= acutValues[2]) { + blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5); + blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5); + nralphainrangelow += 1; + nralphainrangehigh += 1; + } + else if (srccolors[j][i][3] <= acutValues[3]) { + blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5); + blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5); + nralphainrangelow += 1; + nralphainrangehigh += 1; + } + else if (srccolors[j][i][3] <= acutValues[4]) { + blockerrlin1 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5); + blockerrlin2 += (srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5); + nralphainrangelow += 1; + nralphainrangehigh += 1; + } + else { + blockerrlin2 += (srccolors[j][i][3] - alphatest[1]); + nralphainrangehigh += 1; + } + } + } + /* shouldn't happen often, needed to avoid div by zero */ + if (nralphainrangelow == 0) nralphainrangelow = 1; + if (nralphainrangehigh == 0) nralphainrangehigh = 1; + alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow); +/* fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow); + fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);*/ + /* again shouldn't really happen often... */ + if (alphatest[0] < 0) { + alphatest[0] = 0; +/* fprintf(stderr, "adj alpha base val to 0\n");*/ + } + alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh); + if (alphatest[1] > 255) { + alphatest[1] = 255; +/* fprintf(stderr, "adj alpha base val to 255\n");*/ + } + + alphablockerror3 = 0; + for (aindex = 0; aindex < 5; aindex++) { + /* don't forget here is always rounded down */ + acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10; + } + for (j = 0; j < numypixels; j++) { + for (i = 0; i < numxpixels; i++) { + /* maybe it's overkill to have the most complicated calculation just for the error + calculation which we only need to figure out if encoding1 or encoding2 is better... */ + if (srccolors[j][i][3] <= alphatest[0] / 2) { + alphaenc3[4*j + i] = 6; + alphadist = srccolors[j][i][3]; + } + else if (srccolors[j][i][3] > ((255 + alphatest[1]) / 2)) { + alphaenc3[4*j + i] = 7; + alphadist = 255 - srccolors[j][i][3]; + } + else if (srccolors[j][i][3] <= acutValues[0]) { + alphaenc3[4*j + i] = 0; + alphadist = srccolors[j][i][3] - alphatest[0]; + } + else if (srccolors[j][i][3] <= acutValues[1]) { + alphaenc3[4*j + i] = 2; + alphadist = srccolors[j][i][3] - (alphatest[0] * 4 + alphatest[1] * 1) / 5; + } + else if (srccolors[j][i][3] <= acutValues[2]) { + alphaenc3[4*j + i] = 3; + alphadist = srccolors[j][i][3] - (alphatest[0] * 3 + alphatest[1] * 2) / 5; + } + else if (srccolors[j][i][3] <= acutValues[3]) { + alphaenc3[4*j + i] = 4; + alphadist = srccolors[j][i][3] - (alphatest[0] * 2 + alphatest[1] * 3) / 5; + } + else if (srccolors[j][i][3] <= acutValues[4]) { + alphaenc3[4*j + i] = 5; + alphadist = srccolors[j][i][3] - (alphatest[0] * 1 + alphatest[1] * 4) / 5; + } + else { + alphaenc3[4*j + i] = 1; + alphadist = srccolors[j][i][3] - alphatest[1]; + } + alphablockerror3 += alphadist * alphadist; + } + } + } + } + /* write the alpha values and encoding back. */ + if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) { +/* if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);*/ + writedxt5encodedalphablock( blkaddr, alphause[1], alphause[0], alphaenc1 ); + } + else if (alphablockerror2 <= alphablockerror3) { +/* if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);*/ + writedxt5encodedalphablock( blkaddr, alphabase[0], alphabase[1], alphaenc2 ); + } + else { +/* fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);*/ + writedxt5encodedalphablock( blkaddr, (GLubyte)alphatest[0], (GLubyte)alphatest[1], alphaenc3 ); + } +} + +static void extractsrccolors( GLubyte srcpixels[4][4][4], const GLchan *srcaddr, + GLint srcRowStride, GLint numxpixels, GLint numypixels, GLint comps) +{ + GLubyte i, j, c; + const GLchan *curaddr; + for (j = 0; j < numypixels; j++) { + curaddr = srcaddr + j * srcRowStride * comps; + for (i = 0; i < numxpixels; i++) { + for (c = 0; c < comps; c++) { + srcpixels[j][i][c] = *curaddr++ / (CHAN_MAX / 255); + } + } + } +} + + +static void tx_compress_dxtn(GLint srccomps, GLint width, GLint height, const GLubyte *srcPixData, + GLenum destFormat, GLubyte *dest, GLint dstRowStride) +{ + GLubyte *blkaddr = dest; + GLubyte srcpixels[4][4][4]; + const GLchan *srcaddr = srcPixData; + GLint numxpixels, numypixels; + GLint i, j; + GLint dstRowDiff; + + switch (destFormat) { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + /* hmm we used to get called without dstRowStride... */ + dstRowDiff = dstRowStride >= (width * 2) ? dstRowStride - (((width + 3) & ~3) * 2) : 0; +/* fprintf(stderr, "dxt1 tex width %d tex height %d dstRowStride %d\n", + width, height, dstRowStride); */ + for (j = 0; j < height; j += 4) { + if (height > j + 3) numypixels = 4; + else numypixels = height - j; + srcaddr = srcPixData + j * width * srccomps; + for (i = 0; i < width; i += 4) { + if (width > i + 3) numxpixels = 4; + else numxpixels = width - i; + extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); + encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat); + srcaddr += srccomps * numxpixels; + blkaddr += 8; + } + blkaddr += dstRowDiff; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0; +/* fprintf(stderr, "dxt3 tex width %d tex height %d dstRowStride %d\n", + width, height, dstRowStride); */ + for (j = 0; j < height; j += 4) { + if (height > j + 3) numypixels = 4; + else numypixels = height - j; + srcaddr = srcPixData + j * width * srccomps; + for (i = 0; i < width; i += 4) { + if (width > i + 3) numxpixels = 4; + else numxpixels = width - i; + extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); + *blkaddr++ = (srcpixels[0][0][3] >> 4) | (srcpixels[0][1][3] & 0xf0); + *blkaddr++ = (srcpixels[0][2][3] >> 4) | (srcpixels[0][3][3] & 0xf0); + *blkaddr++ = (srcpixels[1][0][3] >> 4) | (srcpixels[1][1][3] & 0xf0); + *blkaddr++ = (srcpixels[1][2][3] >> 4) | (srcpixels[1][3][3] & 0xf0); + *blkaddr++ = (srcpixels[2][0][3] >> 4) | (srcpixels[2][1][3] & 0xf0); + *blkaddr++ = (srcpixels[2][2][3] >> 4) | (srcpixels[2][3][3] & 0xf0); + *blkaddr++ = (srcpixels[3][0][3] >> 4) | (srcpixels[3][1][3] & 0xf0); + *blkaddr++ = (srcpixels[3][2][3] >> 4) | (srcpixels[3][3][3] & 0xf0); + encodedxtcolorblockfaster(blkaddr, srcpixels, numxpixels, numypixels, destFormat); + srcaddr += srccomps * numxpixels; + blkaddr += 8; + } + blkaddr += dstRowDiff; + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + dstRowDiff = dstRowStride >= (width * 4) ? dstRowStride - (((width + 3) & ~3) * 4) : 0; +/* fprintf(stderr, "dxt5 tex width %d tex height %d dstRowStride %d\n", + width, height, dstRowStride); */ + for (j = 0; j < height; j += 4) { + if (height > j + 3) numypixels = 4; + else numypixels = height - j; + srcaddr = srcPixData + j * width * srccomps; + for (i = 0; i < width; i += 4) { + if (width > i + 3) numxpixels = 4; + else numxpixels = width - i; + extractsrccolors(srcpixels, srcaddr, width, numxpixels, numypixels, srccomps); + encodedxt5alpha(blkaddr, srcpixels, numxpixels, numypixels); + encodedxtcolorblockfaster(blkaddr + 8, srcpixels, numxpixels, numypixels, destFormat); + srcaddr += srccomps * numxpixels; + blkaddr += 16; + } + blkaddr += dstRowDiff; + } + break; + default: + assert(false); + return; + } +} diff --git a/lib/mesa/src/mesa/main/texformat.c b/lib/mesa/src/mesa/main/texformat.c index baa3988f0..822f80f89 100644 --- a/lib/mesa/src/mesa/main/texformat.c +++ b/lib/mesa/src/mesa/main/texformat.c @@ -88,6 +88,7 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, break; case GL_RGB5_A1: RETURN_IF_SUPPORTED(MESA_FORMAT_B5G5R5A1_UNORM); + RETURN_IF_SUPPORTED(MESA_FORMAT_A1B5G5R5_UNORM); break; case GL_RGBA2: RETURN_IF_SUPPORTED(MESA_FORMAT_A4R4G4B4_UNORM); /* just to test another format*/ @@ -117,6 +118,9 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, if (type == GL_UNSIGNED_INT_2_10_10_10_REV) { RETURN_IF_SUPPORTED(MESA_FORMAT_B10G10R10A2_UNORM); } + if (type == GL_UNSIGNED_SHORT_5_6_5) { + RETURN_IF_SUPPORTED(MESA_FORMAT_B5G6R5_UNORM); + } /* fallthrough */ case GL_RGB8: RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_UNORM8); @@ -249,9 +253,7 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, * 1D ARRAY textures in S3TC format. */ if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) { - if (ctx->Mesa_DXTn) - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); - RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_FXT1); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGB_DXT1); } RETURN_IF_SUPPORTED(MESA_FORMAT_BGR_UNORM8); RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8X8_UNORM); @@ -260,9 +262,7 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, case GL_COMPRESSED_RGBA_ARB: /* We don't use texture compression for 1D and 1D array textures. */ if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) { - if (ctx->Mesa_DXTn) - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); /* Not rgba_dxt1, see spec */ - RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_FXT1); + RETURN_IF_SUPPORTED(MESA_FORMAT_RGBA_DXT3); /* Not rgba_dxt1, see spec */ } RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_UNORM); RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_UNORM); @@ -502,15 +502,13 @@ _mesa_choose_tex_format(struct gl_context *ctx, GLenum target, RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB); break; case GL_COMPRESSED_SRGB_EXT: - if (ctx->Mesa_DXTn) - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1); + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGB_DXT1); RETURN_IF_SUPPORTED(MESA_FORMAT_BGR_SRGB8); RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB); RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB); break; case GL_COMPRESSED_SRGB_ALPHA_EXT: - if (ctx->Mesa_DXTn) - RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); /* Not srgba_dxt1, see spec */ + RETURN_IF_SUPPORTED(MESA_FORMAT_SRGBA_DXT3); /* Not srgba_dxt1, see spec */ RETURN_IF_SUPPORTED(MESA_FORMAT_A8B8G8R8_SRGB); RETURN_IF_SUPPORTED(MESA_FORMAT_B8G8R8A8_SRGB); RETURN_IF_SUPPORTED(MESA_FORMAT_A8R8G8B8_SRGB); diff --git a/lib/mesa/src/mesa/main/textureview.h b/lib/mesa/src/mesa/main/textureview.h index 39b415d87..e2f18aed0 100644 --- a/lib/mesa/src/mesa/main/textureview.h +++ b/lib/mesa/src/mesa/main/textureview.h @@ -42,6 +42,12 @@ GLenum _mesa_texture_view_lookup_view_class(const struct gl_context *ctx, GLenum internalformat); +void GLAPIENTRY +_mesa_TextureView_no_error(GLuint texture, GLenum target, GLuint origtexture, + GLenum internalformat, + GLuint minlevel, GLuint numlevels, + GLuint minlayer, GLuint numlayers); + extern void GLAPIENTRY _mesa_TextureView(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, diff --git a/lib/mesa/src/mesa/main/version.h b/lib/mesa/src/mesa/main/version.h index ee7cb7501..adfec6f82 100644 --- a/lib/mesa/src/mesa/main/version.h +++ b/lib/mesa/src/mesa/main/version.h @@ -47,4 +47,15 @@ _mesa_override_gl_version(struct gl_context *ctx); extern void _mesa_override_glsl_version(struct gl_constants *consts); +extern void +_mesa_get_driver_uuid(struct gl_context *ctx, GLint *uuid); + +extern void +_mesa_get_device_uuid(struct gl_context *ctx, GLint *uuid); + +extern int +_mesa_get_shading_language_version(const struct gl_context *ctx, + int index, + char **versionOut); + #endif /* VERSION_H */ diff --git a/lib/mesa/src/mesa/state_tracker/st_cb_bufferobjects.h b/lib/mesa/src/mesa/state_tracker/st_cb_bufferobjects.h index 54e6a21ce..b9f91b074 100644 --- a/lib/mesa/src/mesa/state_tracker/st_cb_bufferobjects.h +++ b/lib/mesa/src/mesa/state_tracker/st_cb_bufferobjects.h @@ -57,12 +57,6 @@ st_buffer_object(struct gl_buffer_object *obj) extern void -st_bufferobj_validate_usage(struct st_context *st, - struct st_buffer_object *obj, - unsigned usage); - - -extern void st_init_bufferobject_functions(struct pipe_screen *screen, struct dd_function_table *functions); diff --git a/lib/mesa/src/mesa/state_tracker/st_cb_drawpixels_shader.c b/lib/mesa/src/mesa/state_tracker/st_cb_drawpixels_shader.c index 35a9da064..83dcfeab4 100644 --- a/lib/mesa/src/mesa/state_tracker/st_cb_drawpixels_shader.c +++ b/lib/mesa/src/mesa/state_tracker/st_cb_drawpixels_shader.c @@ -204,6 +204,8 @@ transform_inst: ctx->info.input_semantic_index[reg] == 0) { src->Register.File = TGSI_FILE_CONSTANT; src->Register.Index = ctx->texcoord_const; + src->Register.Dimension = 1; + src->Dimension.Index = 0; } } diff --git a/lib/mesa/src/mesa/state_tracker/st_cb_flush.c b/lib/mesa/src/mesa/state_tracker/st_cb_flush.c index 6442fc922..d9ec0a846 100644 --- a/lib/mesa/src/mesa/state_tracker/st_cb_flush.c +++ b/lib/mesa/src/mesa/state_tracker/st_cb_flush.c @@ -46,35 +46,6 @@ #include "util/u_gen_mipmap.h" -/** Check if we have a front color buffer and if it's been drawn to. */ -static inline GLboolean -is_front_buffer_dirty(struct st_context *st) -{ - struct gl_framebuffer *fb = st->ctx->DrawBuffer; - struct st_renderbuffer *strb - = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); - return strb && strb->defined; -} - - -/** - * Tell the screen to display the front color buffer on-screen. - */ -static void -display_front_buffer(struct st_context *st) -{ - struct gl_framebuffer *fb = st->ctx->DrawBuffer; - struct st_renderbuffer *strb - = st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer); - - if (strb) { - /* Hook for copying "fake" frontbuffer if necessary: - */ - st_manager_flush_frontbuffer(st); - } -} - - void st_flush(struct st_context *st, struct pipe_fence_handle **fence, unsigned flags) @@ -102,6 +73,8 @@ void st_finish( struct st_context *st ) PIPE_TIMEOUT_INFINITE); st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL); } + + st_manager_flush_swapbuffers(); } @@ -120,9 +93,7 @@ static void st_glFlush(struct gl_context *ctx) */ st_flush(st, NULL, 0); - if (is_front_buffer_dirty(st)) { - display_front_buffer(st); - } + st_manager_flush_frontbuffer(st); } @@ -135,9 +106,7 @@ static void st_glFinish(struct gl_context *ctx) st_finish(st); - if (is_front_buffer_dirty(st)) { - display_front_buffer(st); - } + st_manager_flush_frontbuffer(st); } @@ -214,16 +183,4 @@ void st_init_flush_functions(struct pipe_screen *screen, if (screen->get_param(screen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) functions->GetGraphicsResetStatus = st_get_graphics_reset_status; - - /* Windows opengl32.dll calls glFinish prior to every swapbuffers. - * This is unnecessary and degrades performance. Luckily we have some - * scope to work around this, as the externally-visible behaviour of - * Finish() is identical to Flush() in all cases - no differences in - * rendering or ReadPixels are visible if we opt not to wait here. - * - * Only set this up on Windows to avoid surprise elsewhere. - */ -#ifdef PIPE_OS_WINDOWS - functions->Finish = st_glFlush; -#endif } diff --git a/lib/mesa/src/mesa/state_tracker/st_cb_memoryobjects.c b/lib/mesa/src/mesa/state_tracker/st_cb_memoryobjects.c new file mode 100644 index 000000000..7a4376326 --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/st_cb_memoryobjects.c @@ -0,0 +1,66 @@ +#include "main/imports.h" +#include "main/mtypes.h" + +#include "main/externalobjects.h" + +#include "st_context.h" +#include "st_cb_memoryobjects.h" + +#include "state_tracker/drm_driver.h" +#include "pipe/p_context.h" +#include "pipe/p_screen.h" + +static struct gl_memory_object * +st_memoryobj_alloc(struct gl_context *ctx, GLuint name) +{ + struct st_memory_object *st_obj = ST_CALLOC_STRUCT(st_memory_object); + if (!st_obj) + return NULL; + + _mesa_initialize_memory_object(ctx, &st_obj->Base, name); + return &st_obj->Base; +} + +static void +st_memoryobj_free(struct gl_context *ctx, + struct gl_memory_object *obj) +{ + _mesa_delete_memory_object(ctx, obj); +} + + +static void +st_import_memoryobj_fd(struct gl_context *ctx, + struct gl_memory_object *obj, + GLuint64 size, + int fd) +{ + struct st_memory_object *st_obj = st_memory_object(obj); + struct st_context *st = st_context(ctx); + struct pipe_context *pipe = st->pipe; + struct pipe_screen *screen = pipe->screen; + struct winsys_handle whandle; + + whandle.type = DRM_API_HANDLE_TYPE_FD; + whandle.handle = fd; + whandle.offset = 0; + whandle.layer = 0; + whandle.stride = 0; + + st_obj->memory = screen->memobj_create_from_handle(screen, + &whandle, + obj->Dedicated); + +#if !defined(_WIN32) + /* We own fd, but we no longer need it. So get rid of it */ + close(fd); +#endif +} + +void +st_init_memoryobject_functions(struct dd_function_table *functions) +{ + functions->NewMemoryObject = st_memoryobj_alloc; + functions->DeleteMemoryObject = st_memoryobj_free; + functions->ImportMemoryObjectFd = st_import_memoryobj_fd; +} diff --git a/lib/mesa/src/mesa/state_tracker/st_cb_memoryobjects.h b/lib/mesa/src/mesa/state_tracker/st_cb_memoryobjects.h new file mode 100644 index 000000000..66065169e --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/st_cb_memoryobjects.h @@ -0,0 +1,25 @@ +#ifndef ST_CB_MEMORYOBJECTS_H +#define ST_CB_MEMORYOBJECTS_H + +#include "main/compiler.h" +#include "main/mtypes.h" + +struct dd_function_table; +struct pipe_screen; + +struct st_memory_object +{ + struct gl_memory_object Base; + struct pipe_memory_object *memory; +}; + +static inline struct st_memory_object * +st_memory_object(struct gl_memory_object *obj) +{ + return (struct st_memory_object *)obj; +} + +extern void +st_init_memoryobject_functions(struct dd_function_table *functions); + +#endif diff --git a/lib/mesa/src/mesa/state_tracker/st_cb_syncobj.c b/lib/mesa/src/mesa/state_tracker/st_cb_syncobj.c index 7a4ba71b3..637fbe3b7 100644 --- a/lib/mesa/src/mesa/state_tracker/st_cb_syncobj.c +++ b/lib/mesa/src/mesa/state_tracker/st_cb_syncobj.c @@ -45,17 +45,12 @@ struct st_sync_object { }; -static struct gl_sync_object * st_new_sync_object(struct gl_context *ctx, - GLenum type) +static struct gl_sync_object *st_new_sync_object(struct gl_context *ctx) { - if (type == GL_SYNC_FENCE) { - struct st_sync_object *so = CALLOC_STRUCT(st_sync_object); + struct st_sync_object *so = CALLOC_STRUCT(st_sync_object); - mtx_init(&so->mutex, mtx_plain); - return &so->b; - } else { - return NULL; - } + mtx_init(&so->mutex, mtx_plain); + return &so->b; } static void st_delete_sync_object(struct gl_context *ctx, diff --git a/lib/mesa/src/mesa/state_tracker/st_extensions.h b/lib/mesa/src/mesa/state_tracker/st_extensions.h index faff11fd5..951185caa 100644 --- a/lib/mesa/src/mesa/state_tracker/st_extensions.h +++ b/lib/mesa/src/mesa/state_tracker/st_extensions.h @@ -40,8 +40,7 @@ extern void st_init_limits(struct pipe_screen *screen, extern void st_init_extensions(struct pipe_screen *screen, struct gl_constants *consts, struct gl_extensions *extensions, - struct st_config_options *options, - boolean has_lib_dxtc); + struct st_config_options *options); #endif /* ST_EXTENSIONS_H */ diff --git a/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_private.cpp b/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_private.cpp new file mode 100644 index 000000000..b664fa7ec --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_private.cpp @@ -0,0 +1,252 @@ +/* + * Copyright © 2010 Intel Corporation + * Copyright © 2011 Bryan Cain + * Copyright © 2017 Gert Wollny + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "st_glsl_to_tgsi_private.h" +#include <tgsi/tgsi_info.h> +#include <mesa/program/prog_instruction.h> + +static int swizzle_for_type(const glsl_type *type, int component = 0) +{ + unsigned num_elements = 4; + + if (type) { + type = type->without_array(); + if (type->is_scalar() || type->is_vector() || type->is_matrix()) + num_elements = type->vector_elements; + } + + int swizzle = swizzle_for_size(num_elements); + assert(num_elements + component <= 4); + + swizzle += component * MAKE_SWIZZLE4(1, 1, 1, 1); + return swizzle; +} + +static st_src_reg * +dup_reladdr(const st_src_reg *input) +{ + if (!input) + return NULL; + + st_src_reg *reg = ralloc(input, st_src_reg); + if (!reg) { + assert(!"can't create reladdr, expect shader breakage"); + return NULL; + } + + *reg = *input; + return reg; +} + +st_src_reg::st_src_reg(gl_register_file file, int index, const glsl_type *type, + int component, unsigned array_id) +{ + assert(file != PROGRAM_ARRAY || array_id != 0); + this->file = file; + this->index = index; + this->swizzle = swizzle_for_type(type, component); + this->negate = 0; + this->abs = 0; + this->index2D = 0; + this->type = type ? type->base_type : GLSL_TYPE_ERROR; + this->reladdr = NULL; + this->reladdr2 = NULL; + this->has_index2 = false; + this->double_reg2 = false; + this->array_id = array_id; + this->is_double_vertex_input = false; +} + +st_src_reg::st_src_reg(gl_register_file file, int index, enum glsl_base_type type) +{ + assert(file != PROGRAM_ARRAY); /* need array_id > 0 */ + this->type = type; + this->file = file; + this->index = index; + this->index2D = 0; + this->swizzle = SWIZZLE_XYZW; + this->negate = 0; + this->abs = 0; + this->reladdr = NULL; + this->reladdr2 = NULL; + this->has_index2 = false; + this->double_reg2 = false; + this->array_id = 0; + this->is_double_vertex_input = false; +} + +st_src_reg::st_src_reg(gl_register_file file, int index, enum glsl_base_type type, int index2D) +{ + assert(file != PROGRAM_ARRAY); /* need array_id > 0 */ + this->type = type; + this->file = file; + this->index = index; + this->index2D = index2D; + this->swizzle = SWIZZLE_XYZW; + this->negate = 0; + this->abs = 0; + this->reladdr = NULL; + this->reladdr2 = NULL; + this->has_index2 = false; + this->double_reg2 = false; + this->array_id = 0; + this->is_double_vertex_input = false; +} + +st_src_reg::st_src_reg() +{ + this->type = GLSL_TYPE_ERROR; + this->file = PROGRAM_UNDEFINED; + this->index = 0; + this->index2D = 0; + this->swizzle = 0; + this->negate = 0; + this->abs = 0; + this->reladdr = NULL; + this->reladdr2 = NULL; + this->has_index2 = false; + this->double_reg2 = false; + this->array_id = 0; + this->is_double_vertex_input = false; +} + +st_src_reg::st_src_reg(const st_src_reg ®) +{ + *this = reg; +} + +void st_src_reg::operator=(const st_src_reg ®) +{ + this->type = reg.type; + this->file = reg.file; + this->index = reg.index; + this->index2D = reg.index2D; + this->swizzle = reg.swizzle; + this->negate = reg.negate; + this->abs = reg.abs; + this->reladdr = dup_reladdr(reg.reladdr); + this->reladdr2 = dup_reladdr(reg.reladdr2); + this->has_index2 = reg.has_index2; + this->double_reg2 = reg.double_reg2; + this->array_id = reg.array_id; + this->is_double_vertex_input = reg.is_double_vertex_input; +} + +st_src_reg::st_src_reg(st_dst_reg reg) +{ + this->type = reg.type; + this->file = reg.file; + this->index = reg.index; + this->swizzle = SWIZZLE_XYZW; + this->negate = 0; + this->abs = 0; + this->reladdr = dup_reladdr(reg.reladdr); + this->index2D = reg.index2D; + this->reladdr2 = dup_reladdr(reg.reladdr2); + this->has_index2 = reg.has_index2; + this->double_reg2 = false; + this->array_id = reg.array_id; + this->is_double_vertex_input = false; +} + +st_src_reg st_src_reg::get_abs() +{ + st_src_reg reg = *this; + reg.negate = 0; + reg.abs = 1; + return reg; +} + +st_dst_reg::st_dst_reg(st_src_reg reg) +{ + this->type = reg.type; + this->file = reg.file; + this->index = reg.index; + this->writemask = WRITEMASK_XYZW; + this->reladdr = dup_reladdr(reg.reladdr); + this->index2D = reg.index2D; + this->reladdr2 = dup_reladdr(reg.reladdr2); + this->has_index2 = reg.has_index2; + this->array_id = reg.array_id; +} + +st_dst_reg::st_dst_reg(gl_register_file file, int writemask, enum glsl_base_type type, int index) +{ + assert(file != PROGRAM_ARRAY); /* need array_id > 0 */ + this->file = file; + this->index = index; + this->index2D = 0; + this->writemask = writemask; + this->reladdr = NULL; + this->reladdr2 = NULL; + this->has_index2 = false; + this->type = type; + this->array_id = 0; +} + +st_dst_reg::st_dst_reg(gl_register_file file, int writemask, enum glsl_base_type type) +{ + assert(file != PROGRAM_ARRAY); /* need array_id > 0 */ + this->file = file; + this->index = 0; + this->index2D = 0; + this->writemask = writemask; + this->reladdr = NULL; + this->reladdr2 = NULL; + this->has_index2 = false; + this->type = type; + this->array_id = 0; +} + +st_dst_reg::st_dst_reg() +{ + this->type = GLSL_TYPE_ERROR; + this->file = PROGRAM_UNDEFINED; + this->index = 0; + this->index2D = 0; + this->writemask = 0; + this->reladdr = NULL; + this->reladdr2 = NULL; + this->has_index2 = false; + this->array_id = 0; +} + +st_dst_reg::st_dst_reg(const st_dst_reg ®) +{ + *this = reg; +} + +void st_dst_reg::operator=(const st_dst_reg ®) +{ + this->type = reg.type; + this->file = reg.file; + this->index = reg.index; + this->writemask = reg.writemask; + this->reladdr = dup_reladdr(reg.reladdr); + this->index2D = reg.index2D; + this->reladdr2 = dup_reladdr(reg.reladdr2); + this->has_index2 = reg.has_index2; + this->array_id = reg.array_id; +} diff --git a/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_private.h b/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_private.h new file mode 100644 index 000000000..d57525d9c --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_private.h @@ -0,0 +1,180 @@ +/* + * Copyright © 2010 Intel Corporation + * Copyright © 2011 Bryan Cain + * Copyright © 2017 Gert Wollny + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 ST_GLSL_TO_TGSI_PRIVATE_H +#define ST_GLSL_TO_TGSI_PRIVATE_H + +#include <mesa/main/mtypes.h> +#include <compiler/glsl_types.h> +#include <compiler/glsl/ir.h> +#include <tgsi/tgsi_info.h> + +int swizzle_for_size(int size); + +class st_dst_reg; +/** + * This struct is a corresponding struct to TGSI ureg_src. + */ +class st_src_reg { +public: + st_src_reg(gl_register_file file, int index, const glsl_type *type, + int component = 0, unsigned array_id = 0); + + st_src_reg(gl_register_file file, int index, enum glsl_base_type type); + + st_src_reg(gl_register_file file, int index, enum glsl_base_type type, int index2D); + + st_src_reg(); + st_src_reg(const st_src_reg ®); + void operator=(const st_src_reg ®); + + explicit st_src_reg(st_dst_reg reg); + + st_src_reg get_abs(); + + int32_t index; /**< temporary index, VERT_ATTRIB_*, VARYING_SLOT_*, etc. */ + int16_t index2D; + + uint16_t swizzle; /**< SWIZZLE_XYZWONEZERO swizzles from Mesa. */ + int negate:4; /**< NEGATE_XYZW mask from mesa */ + unsigned abs:1; + enum glsl_base_type type:5; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */ + unsigned has_index2:1; + gl_register_file file:5; /**< PROGRAM_* from Mesa */ + /* + * Is this the second half of a double register pair? + * currently used for input mapping only. + */ + unsigned double_reg2:1; + unsigned is_double_vertex_input:1; + unsigned array_id:10; + /** Register index should be offset by the integer in this reg. */ + st_src_reg *reladdr; + st_src_reg *reladdr2; + + bool is_legal_tgsi_address_operand() const + { + /* 2D registers can't be used as an address operand, or if the address + * operand itself is a result of indirect addressing. + */ + return (type == GLSL_TYPE_INT || type == GLSL_TYPE_UINT) && + !has_index2 && !reladdr && !reladdr2; + } +}; + +class st_dst_reg { +public: + st_dst_reg(gl_register_file file, int writemask, enum glsl_base_type type, int index); + + st_dst_reg(gl_register_file file, int writemask, enum glsl_base_type type); + + st_dst_reg(); + st_dst_reg(const st_dst_reg ®); + void operator=(const st_dst_reg ®); + + explicit st_dst_reg(st_src_reg reg); + + int32_t index; /**< temporary index, VERT_ATTRIB_*, VARYING_SLOT_*, etc. */ + int16_t index2D; + gl_register_file file:5; /**< PROGRAM_* from Mesa */ + unsigned writemask:4; /**< Bitfield of WRITEMASK_[XYZW] */ + enum glsl_base_type type:5; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */ + unsigned has_index2:1; + unsigned array_id:10; + + /** Register index should be offset by the integer in this reg. */ + st_src_reg *reladdr; + st_src_reg *reladdr2; +}; + +class glsl_to_tgsi_instruction : public exec_node { +public: + DECLARE_RALLOC_CXX_OPERATORS(glsl_to_tgsi_instruction) + + st_dst_reg dst[2]; + st_src_reg src[4]; + st_src_reg resource; /**< sampler or buffer register */ + st_src_reg *tex_offsets; + + /** Pointer to the ir source this tree came fe02549fdrom for debugging */ + ir_instruction *ir; + + unsigned op:8; /**< TGSI opcode */ + unsigned precise:1; + unsigned saturate:1; + unsigned is_64bit_expanded:1; + unsigned sampler_base:5; + unsigned sampler_array_size:6; /**< 1-based size of sampler array, 1 if not array */ + unsigned tex_target:4; /**< One of TEXTURE_*_INDEX */ + glsl_base_type tex_type:5; + unsigned tex_shadow:1; + unsigned image_format:9; + unsigned tex_offset_num_offset:3; + unsigned dead_mask:4; /**< Used in dead code elimination */ + unsigned buffer_access:3; /**< buffer access type */ + + const struct tgsi_opcode_info *info; +}; + +struct rename_reg_pair { + bool valid; + int new_reg; +}; + +inline static bool +is_resource_instruction(unsigned opcode) +{ + switch (opcode) { + case TGSI_OPCODE_RESQ: + case TGSI_OPCODE_LOAD: + case TGSI_OPCODE_ATOMUADD: + case TGSI_OPCODE_ATOMXCHG: + case TGSI_OPCODE_ATOMCAS: + case TGSI_OPCODE_ATOMAND: + case TGSI_OPCODE_ATOMOR: + case TGSI_OPCODE_ATOMXOR: + case TGSI_OPCODE_ATOMUMIN: + case TGSI_OPCODE_ATOMUMAX: + case TGSI_OPCODE_ATOMIMIN: + case TGSI_OPCODE_ATOMIMAX: + return true; + default: + return false; + } +} + +inline static unsigned +num_inst_dst_regs(const glsl_to_tgsi_instruction *op) +{ + return op->info->num_dst; +} + +inline static unsigned +num_inst_src_regs(const glsl_to_tgsi_instruction *op) +{ + return op->info->is_tex || is_resource_instruction(op->op) ? + op->info->num_src - 1 : op->info->num_src; +} +#endif diff --git a/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp b/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp new file mode 100644 index 000000000..76c198e16 --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.cpp @@ -0,0 +1,1010 @@ +/* + * Copyright © 2017 Gert Wollny + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "st_glsl_to_tgsi_temprename.h" +#include <tgsi/tgsi_info.h> +#include <tgsi/tgsi_strings.h> +#include <program/prog_instruction.h> +#include <limits> +#include <cstdlib> + +/* std::sort is significantly faster than qsort */ +#define USE_STL_SORT +#ifdef USE_STL_SORT +#include <algorithm> +#endif + +#ifndef NDEBUG +#include <iostream> +#include <iomanip> +#include <program/prog_print.h> +#include <util/debug.h> +using std::cerr; +using std::setw; +#endif + +/* If <windows.h> is included this is defined and clashes with + * std::numeric_limits<>::max() + */ +#ifdef max +#undef max +#endif + +using std::numeric_limits; + +/* Without c++11 define the nullptr for forward-compatibility + * and better readibility */ +#if __cplusplus < 201103L +#define nullptr 0 +#endif + +#ifndef NDEBUG +/* Helper function to check whether we want to seen debugging output */ +static inline bool is_debug_enabled () +{ + static int debug_enabled = -1; + if (debug_enabled < 0) + debug_enabled = env_var_as_boolean("GLSL_TO_TGSI_RENAME_DEBUG", false); + return debug_enabled > 0; +} +#define RENAME_DEBUG(X) if (is_debug_enabled()) do { X; } while (false); +#else +#define RENAME_DEBUG(X) +#endif + +namespace { + +enum prog_scope_type { + outer_scope, /* Outer program scope */ + loop_body, /* Inside a loop */ + if_branch, /* Inside if branch */ + else_branch, /* Inside else branch */ + switch_body, /* Inside switch statmenet */ + switch_case_branch, /* Inside switch case statmenet */ + switch_default_branch, /* Inside switch default statmenet */ + undefined_scope +}; + +class prog_scope { +public: + prog_scope(prog_scope *parent, prog_scope_type type, int id, + int depth, int begin); + + prog_scope_type type() const; + prog_scope *parent() const; + int nesting_depth() const; + int id() const; + int end() const; + int begin() const; + int loop_break_line() const; + + const prog_scope *in_ifelse_scope() const; + const prog_scope *in_switchcase_scope() const; + const prog_scope *innermost_loop() const; + const prog_scope *outermost_loop() const; + const prog_scope *enclosing_conditional() const; + + bool is_loop() const; + bool is_in_loop() const; + bool is_conditional() const; + + bool break_is_for_switchcase() const; + bool contains_range_of(const prog_scope& other) const; + + void set_end(int end); + void set_loop_break_line(int line); + +private: + prog_scope_type scope_type; + int scope_id; + int scope_nesting_depth; + int scope_begin; + int scope_end; + int break_loop_line; + prog_scope *parent_scope; +}; + +/* Some storage class to encapsulate the prog_scope (de-)allocations */ +class prog_scope_storage { +public: + prog_scope_storage(void *mem_ctx, int n); + ~prog_scope_storage(); + prog_scope * create(prog_scope *p, prog_scope_type type, int id, + int lvl, int s_begin); +private: + void *mem_ctx; + int current_slot; + prog_scope *storage; +}; + +class temp_comp_access { +public: + temp_comp_access(); + void record_read(int line, prog_scope *scope); + void record_write(int line, prog_scope *scope); + lifetime get_required_lifetime(); +private: + void propagate_lifetime_to_dominant_write_scope(); + + prog_scope *last_read_scope; + prog_scope *first_read_scope; + prog_scope *first_write_scope; + int first_write; + int last_read; + int last_write; + int first_read; + bool keep_for_full_loop; +}; + +class temp_access { +public: + temp_access(); + void record_read(int line, prog_scope *scope, int swizzle); + void record_write(int line, prog_scope *scope, int writemask); + lifetime get_required_lifetime(); +private: + void update_access_mask(int mask); + + temp_comp_access comp[4]; + int access_mask; + bool needs_component_tracking; +}; + +prog_scope_storage::prog_scope_storage(void *mc, int n): + mem_ctx(mc), + current_slot(0) +{ + storage = ralloc_array(mem_ctx, prog_scope, n); +} + +prog_scope_storage::~prog_scope_storage() +{ + ralloc_free(storage); +} + +prog_scope* +prog_scope_storage::create(prog_scope *p, prog_scope_type type, int id, + int lvl, int s_begin) +{ + storage[current_slot] = prog_scope(p, type, id, lvl, s_begin); + return &storage[current_slot++]; +} + +prog_scope::prog_scope(prog_scope *parent, prog_scope_type type, int id, + int depth, int scope_begin): + scope_type(type), + scope_id(id), + scope_nesting_depth(depth), + scope_begin(scope_begin), + scope_end(-1), + break_loop_line(numeric_limits<int>::max()), + parent_scope(parent) +{ +} + +prog_scope_type prog_scope::type() const +{ + return scope_type; +} + +prog_scope *prog_scope::parent() const +{ + return parent_scope; +} + +int prog_scope::nesting_depth() const +{ + return scope_nesting_depth; +} + +bool prog_scope::is_loop() const +{ + return (scope_type == loop_body); +} + +bool prog_scope::is_in_loop() const +{ + if (scope_type == loop_body) + return true; + + if (parent_scope) + return parent_scope->is_in_loop(); + + return false; +} + +const prog_scope *prog_scope::innermost_loop() const +{ + if (scope_type == loop_body) + return this; + + if (parent_scope) + return parent_scope->innermost_loop(); + + return nullptr; +} + +const prog_scope *prog_scope::outermost_loop() const +{ + const prog_scope *loop = nullptr; + const prog_scope *p = this; + + do { + if (p->type() == loop_body) + loop = p; + p = p->parent(); + } while (p); + + return loop; +} + +const prog_scope *prog_scope::enclosing_conditional() const +{ + if (is_conditional()) + return this; + + if (parent_scope) + return parent_scope->enclosing_conditional(); + + return nullptr; +} + +bool prog_scope::contains_range_of(const prog_scope& other) const +{ + return (begin() <= other.begin()) && (end() >= other.end()); +} + +bool prog_scope::is_conditional() const +{ + return scope_type == if_branch || + scope_type == else_branch || + scope_type == switch_case_branch || + scope_type == switch_default_branch; +} + +const prog_scope *prog_scope::in_ifelse_scope() const +{ + if (scope_type == if_branch || + scope_type == else_branch) + return this; + + if (parent_scope) + return parent_scope->in_ifelse_scope(); + + return nullptr; +} + +const prog_scope *prog_scope::in_switchcase_scope() const +{ + if (scope_type == switch_case_branch || + scope_type == switch_default_branch) + return this; + + if (parent_scope) + return parent_scope->in_switchcase_scope(); + + return nullptr; +} + +bool prog_scope::break_is_for_switchcase() const +{ + if (scope_type == loop_body) + return false; + + if (scope_type == switch_case_branch || + scope_type == switch_default_branch || + scope_type == switch_body) + return true; + + if (parent_scope) + return parent_scope->break_is_for_switchcase(); + + return false; +} + +int prog_scope::id() const +{ + return scope_id; +} + +int prog_scope::begin() const +{ + return scope_begin; +} + +int prog_scope::end() const +{ + return scope_end; +} + +void prog_scope::set_end(int end) +{ + if (scope_end == -1) + scope_end = end; +} + +void prog_scope::set_loop_break_line(int line) +{ + if (scope_type == loop_body) { + break_loop_line = MIN2(break_loop_line, line); + } else { + if (parent_scope) + parent()->set_loop_break_line(line); + } +} + +int prog_scope::loop_break_line() const +{ + return break_loop_line; +} + +temp_access::temp_access(): + access_mask(0), + needs_component_tracking(false) +{ +} + +void temp_access::update_access_mask(int mask) +{ + if (access_mask && access_mask != mask) + needs_component_tracking = true; + access_mask |= mask; +} + +void temp_access::record_write(int line, prog_scope *scope, int writemask) +{ + update_access_mask(writemask); + + if (writemask & WRITEMASK_X) + comp[0].record_write(line, scope); + if (writemask & WRITEMASK_Y) + comp[1].record_write(line, scope); + if (writemask & WRITEMASK_Z) + comp[2].record_write(line, scope); + if (writemask & WRITEMASK_W) + comp[3].record_write(line, scope); +} + +void temp_access::record_read(int line, prog_scope *scope, int swizzle) +{ + int readmask = 0; + for (int idx = 0; idx < 4; ++idx) { + int swz = GET_SWZ(swizzle, idx); + readmask |= (1 << swz) & 0xF; + } + update_access_mask(readmask); + + if (readmask & WRITEMASK_X) + comp[0].record_read(line, scope); + if (readmask & WRITEMASK_Y) + comp[1].record_read(line, scope); + if (readmask & WRITEMASK_Z) + comp[2].record_read(line, scope); + if (readmask & WRITEMASK_W) + comp[3].record_read(line, scope); +} + +inline static lifetime make_lifetime(int b, int e) +{ + lifetime lt; + lt.begin = b; + lt.end = e; + return lt; +} + +lifetime temp_access::get_required_lifetime() +{ + lifetime result = make_lifetime(-1, -1); + + unsigned mask = access_mask; + while (mask) { + unsigned chan = u_bit_scan(&mask); + lifetime lt = comp[chan].get_required_lifetime(); + + if (lt.begin >= 0) { + if ((result.begin < 0) || (result.begin > lt.begin)) + result.begin = lt.begin; + } + + if (lt.end > result.end) + result.end = lt.end; + + if (!needs_component_tracking) + break; + } + return result; +} + +temp_comp_access::temp_comp_access(): + last_read_scope(nullptr), + first_read_scope(nullptr), + first_write_scope(nullptr), + first_write(-1), + last_read(-1), + last_write(-1), + first_read(numeric_limits<int>::max()) +{ +} + +void temp_comp_access::record_read(int line, prog_scope *scope) +{ + last_read_scope = scope; + last_read = line; + + if (first_read > line) { + first_read = line; + first_read_scope = scope; + } +} + +void temp_comp_access::record_write(int line, prog_scope *scope) +{ + last_write = line; + + if (first_write < 0) { + first_write = line; + first_write_scope = scope; + } +} + +void temp_comp_access::propagate_lifetime_to_dominant_write_scope() +{ + first_write = first_write_scope->begin(); + int lr = first_write_scope->end(); + + if (last_read < lr) + last_read = lr; +} + +lifetime temp_comp_access::get_required_lifetime() +{ + bool keep_for_full_loop = false; + + /* This register component is not used at all, or only read, + * mark it as unused and ignore it when renaming. + * glsl_to_tgsi_visitor::renumber_registers will take care of + * eliminating registers that are not written to. + */ + if (last_write < 0) + return make_lifetime(-1, -1); + + assert(first_write_scope); + + /* Only written to, just make sure the register component is not + * reused in the range it is used to write to + */ + if (!last_read_scope) + return make_lifetime(first_write, last_write + 1); + + const prog_scope *enclosing_scope_first_read = first_read_scope; + const prog_scope *enclosing_scope_first_write = first_write_scope; + + /* We read before writing in a loop + * hence the value must survive the loops + */ + if ((first_read <= first_write) && + first_read_scope->is_in_loop()) { + keep_for_full_loop = true; + enclosing_scope_first_read = first_read_scope->outermost_loop(); + } + + /* A conditional write within a nested loop must survive + * the outermost loop, but only if it is read outside + * the condition scope where we write. + */ + const prog_scope *conditional = enclosing_scope_first_write->enclosing_conditional(); + if (conditional && conditional->is_in_loop() && + !conditional->contains_range_of(*last_read_scope)) { + keep_for_full_loop = true; + enclosing_scope_first_write = conditional->outermost_loop(); + } + + /* Evaluate the scope that is shared by all: required first write scope, + * required first read before write scope, and last read scope. + */ + const prog_scope *enclosing_scope = enclosing_scope_first_read; + if (enclosing_scope_first_write->contains_range_of(*enclosing_scope)) + enclosing_scope = enclosing_scope_first_write; + + if (last_read_scope->contains_range_of(*enclosing_scope)) + enclosing_scope = last_read_scope; + + while (!enclosing_scope->contains_range_of(*enclosing_scope_first_write) || + !enclosing_scope->contains_range_of(*last_read_scope)) { + enclosing_scope = enclosing_scope->parent(); + assert(enclosing_scope); + } + + /* Propagate the last read scope to the target scope */ + while (enclosing_scope->nesting_depth() < last_read_scope->nesting_depth()) { + /* If the read is in a loop and we have to move up the scope we need to + * extend the life time to the end of this current loop because at this + * point we don't know whether the component was written before + * un-conditionally in the same loop. + */ + if (last_read_scope->is_loop()) + last_read = last_read_scope->end(); + + last_read_scope = last_read_scope->parent(); + } + + /* If the variable has to be kept for the whole loop, and we + * are currently in a loop, then propagate the life time. + */ + if (keep_for_full_loop && first_write_scope->is_loop()) + propagate_lifetime_to_dominant_write_scope(); + + /* Propagate the first_dominant_write scope to the target scope */ + while (enclosing_scope->nesting_depth() < first_write_scope->nesting_depth()) { + /* Propagate lifetime if there was a break in a loop and the write was + * after the break inside that loop. Note, that this is only needed if + * we move up in the scopes. + */ + if (first_write_scope->loop_break_line() < first_write) { + keep_for_full_loop = true; + propagate_lifetime_to_dominant_write_scope(); + } + + first_write_scope = first_write_scope->parent(); + + /* Propagte lifetime if we are now in a loop */ + if (keep_for_full_loop && first_write_scope->is_loop()) + propagate_lifetime_to_dominant_write_scope(); + } + + /* The last write past the last read is dead code, but we have to + * ensure that the component is not reused too early, hence extend the + * lifetime past the last write. + */ + if (last_write >= last_read) + last_read = last_write + 1; + + /* Here we are at the same scope, all is resolved */ + return make_lifetime(first_write, last_read); +} + +/* Helper class for sorting and searching the registers based + * on life times. */ +class access_record { +public: + int begin; + int end; + int reg; + bool erase; + + bool operator < (const access_record& rhs) const { + return begin < rhs.begin; + } +}; + +} + +#ifndef NDEBUG +/* Function used for debugging. */ +static void dump_instruction(int line, prog_scope *scope, + const glsl_to_tgsi_instruction& inst); +#endif + +/* Scan the program and estimate the required register life times. + * The array lifetimes must be pre-allocated + */ +bool +get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions, + int ntemps, struct lifetime *lifetimes) +{ + int line = 0; + int loop_id = 0; + int if_id = 0; + int switch_id = 0; + bool is_at_end = false; + bool ok = true; + int n_scopes = 1; + + /* Count scopes to allocate the needed space without the need for + * re-allocation + */ + foreach_in_list(glsl_to_tgsi_instruction, inst, instructions) { + if (inst->op == TGSI_OPCODE_BGNLOOP || + inst->op == TGSI_OPCODE_SWITCH || + inst->op == TGSI_OPCODE_CASE || + inst->op == TGSI_OPCODE_IF || + inst->op == TGSI_OPCODE_UIF || + inst->op == TGSI_OPCODE_ELSE || + inst->op == TGSI_OPCODE_DEFAULT) + ++n_scopes; + } + + prog_scope_storage scopes(mem_ctx, n_scopes); + temp_access *acc = new temp_access[ntemps]; + + prog_scope *cur_scope = scopes.create(nullptr, outer_scope, 0, 0, line); + + RENAME_DEBUG(cerr << "========= Begin shader ============\n"); + + foreach_in_list(glsl_to_tgsi_instruction, inst, instructions) { + if (is_at_end) { + assert(!"GLSL_TO_TGSI: shader has instructions past end marker"); + break; + } + + RENAME_DEBUG(dump_instruction(line, cur_scope, *inst)); + + switch (inst->op) { + case TGSI_OPCODE_BGNLOOP: { + cur_scope = scopes.create(cur_scope, loop_body, loop_id++, + cur_scope->nesting_depth() + 1, line); + break; + } + case TGSI_OPCODE_ENDLOOP: { + cur_scope->set_end(line); + cur_scope = cur_scope->parent(); + assert(cur_scope); + break; + } + case TGSI_OPCODE_IF: + case TGSI_OPCODE_UIF: { + assert(num_inst_src_regs(inst) == 1); + const st_src_reg& src = inst->src[0]; + if (src.file == PROGRAM_TEMPORARY) + acc[src.index].record_read(line, cur_scope, src.swizzle); + cur_scope = scopes.create(cur_scope, if_branch, if_id++, + cur_scope->nesting_depth() + 1, line + 1); + break; + } + case TGSI_OPCODE_ELSE: { + assert(cur_scope->type() == if_branch); + cur_scope->set_end(line - 1); + cur_scope = scopes.create(cur_scope->parent(), else_branch, + cur_scope->id(), cur_scope->nesting_depth(), + line + 1); + break; + } + case TGSI_OPCODE_END: { + cur_scope->set_end(line); + is_at_end = true; + break; + } + case TGSI_OPCODE_ENDIF: { + cur_scope->set_end(line - 1); + cur_scope = cur_scope->parent(); + assert(cur_scope); + break; + } + case TGSI_OPCODE_SWITCH: { + assert(num_inst_src_regs(inst) == 1); + const st_src_reg& src = inst->src[0]; + prog_scope *scope = scopes.create(cur_scope, switch_body, switch_id++, + cur_scope->nesting_depth() + 1, line); + /* We record the read only for the SWITCH statement itself, like it + * is used by the only consumer of TGSI_OPCODE_SWITCH in tgsi_exec.c. + */ + if (src.file == PROGRAM_TEMPORARY) + acc[src.index].record_read(line, cur_scope, src.swizzle); + cur_scope = scope; + break; + } + case TGSI_OPCODE_ENDSWITCH: { + cur_scope->set_end(line - 1); + /* Remove the case level, it might not have been + * closed with a break. + */ + if (cur_scope->type() != switch_body) + cur_scope = cur_scope->parent(); + + cur_scope = cur_scope->parent(); + assert(cur_scope); + break; + } + case TGSI_OPCODE_CASE: { + /* Take care of tracking the registers. */ + prog_scope *switch_scope = cur_scope->type() == switch_body ? + cur_scope : cur_scope->parent(); + + assert(num_inst_src_regs(inst) == 1); + const st_src_reg& src = inst->src[0]; + if (src.file == PROGRAM_TEMPORARY) + acc[src.index].record_read(line, switch_scope, src.swizzle); + + /* Fall through to allocate the scope. */ + } + case TGSI_OPCODE_DEFAULT: { + prog_scope_type t = inst->op == TGSI_OPCODE_CASE ? switch_case_branch + : switch_default_branch; + prog_scope *switch_scope = (cur_scope->type() == switch_body) ? + cur_scope : cur_scope->parent(); + assert(switch_scope->type() == switch_body); + prog_scope *scope = scopes.create(switch_scope, t, + switch_scope->id(), + switch_scope->nesting_depth() + 1, + line); + /* Previous case falls through, so scope was not yet closed. */ + if ((cur_scope != switch_scope) && (cur_scope->end() == -1)) + cur_scope->set_end(line - 1); + cur_scope = scope; + break; + } + case TGSI_OPCODE_BRK: { + if (cur_scope->break_is_for_switchcase()) { + cur_scope->set_end(line - 1); + } else { + cur_scope->set_loop_break_line(line); + } + break; + } + case TGSI_OPCODE_CAL: + case TGSI_OPCODE_RET: + /* These opcodes are not supported and if a subroutine would + * be called in a shader, then the lifetime tracking would have + * to follow that call to see which registers are used there. + * Since this is not done, we have to bail out here and signal + * that no register merge will take place. + */ + ok = false; + goto out; + default: { + for (unsigned j = 0; j < num_inst_src_regs(inst); j++) { + const st_src_reg& src = inst->src[j]; + if (src.file == PROGRAM_TEMPORARY) + acc[src.index].record_read(line, cur_scope, src.swizzle); + } + for (unsigned j = 0; j < inst->tex_offset_num_offset; j++) { + const st_src_reg& src = inst->tex_offsets[j]; + if (src.file == PROGRAM_TEMPORARY) + acc[src.index].record_read(line, cur_scope, src.swizzle); + } + for (unsigned j = 0; j < num_inst_dst_regs(inst); j++) { + const st_dst_reg& dst = inst->dst[j]; + if (dst.file == PROGRAM_TEMPORARY) + acc[dst.index].record_write(line, cur_scope, dst.writemask); + } + } + } + ++line; + } + + RENAME_DEBUG(cerr << "==================================\n\n"); + + /* Make sure last scope is closed, even though no + * TGSI_OPCODE_END was given. + */ + if (cur_scope->end() < 0) + cur_scope->set_end(line - 1); + + RENAME_DEBUG(cerr << "========= lifetimes ==============\n"); + for(int i = 0; i < ntemps; ++i) { + RENAME_DEBUG(cerr << setw(4) << i); + lifetimes[i] = acc[i].get_required_lifetime(); + RENAME_DEBUG(cerr << ": [" << lifetimes[i].begin << ", " + << lifetimes[i].end << "]\n"); + } + RENAME_DEBUG(cerr << "==================================\n\n"); + +out: + delete[] acc; + return ok; +} + +/* Find the next register between [start, end) that has a life time starting + * at or after bound by using a binary search. + * start points at the beginning of the search range, + * end points at the element past the end of the search range, and + * the array comprising [start, end) must be sorted in ascending order. + */ +static access_record* +find_next_rename(access_record* start, access_record* end, int bound) +{ + int delta = (end - start); + + while (delta > 0) { + int half = delta >> 1; + access_record* middle = start + half; + + if (bound <= middle->begin) { + delta = half; + } else { + start = middle; + ++start; + delta -= half + 1; + } + } + + return start; +} + +#ifndef USE_STL_SORT +static int access_record_compare (const void *a, const void *b) { + const access_record *aa = static_cast<const access_record*>(a); + const access_record *bb = static_cast<const access_record*>(b); + return aa->begin < bb->begin ? -1 : (aa->begin > bb->begin ? 1 : 0); +} +#endif + +/* This functions evaluates the register merges by using a binary + * search to find suitable merge candidates. */ +void get_temp_registers_remapping(void *mem_ctx, int ntemps, + const struct lifetime* lifetimes, + struct rename_reg_pair *result) +{ + access_record *reg_access = ralloc_array(mem_ctx, access_record, ntemps); + + int used_temps = 0; + for (int i = 0; i < ntemps; ++i) { + if (lifetimes[i].begin >= 0) { + reg_access[used_temps].begin = lifetimes[i].begin; + reg_access[used_temps].end = lifetimes[i].end; + reg_access[used_temps].reg = i; + reg_access[used_temps].erase = false; + ++used_temps; + } + } + +#ifdef USE_STL_SORT + std::sort(reg_access, reg_access + used_temps); +#else + std::qsort(reg_access, used_temps, sizeof(access_record), access_record_compare); +#endif + + access_record *trgt = reg_access; + access_record *reg_access_end = reg_access + used_temps; + access_record *first_erase = reg_access_end; + access_record *search_start = trgt + 1; + + while (trgt != reg_access_end) { + access_record *src = find_next_rename(search_start, reg_access_end, + trgt->end); + if (src != reg_access_end) { + result[src->reg].new_reg = trgt->reg; + result[src->reg].valid = true; + trgt->end = src->end; + + /* Since we only search forward, don't remove the renamed + * register just now, only mark it. */ + src->erase = true; + + if (first_erase == reg_access_end) + first_erase = src; + + search_start = src + 1; + } else { + /* Moving to the next target register it is time to remove + * the already merged registers from the search range */ + if (first_erase != reg_access_end) { + access_record *outp = first_erase; + access_record *inp = first_erase + 1; + + while (inp != reg_access_end) { + if (!inp->erase) + *outp++ = *inp; + ++inp; + } + + reg_access_end = outp; + first_erase = reg_access_end; + } + ++trgt; + search_start = trgt + 1; + } + } + ralloc_free(reg_access); +} + +/* Code below used for debugging */ +#ifndef NDEBUG +static const char swizzle_txt[] = "xyzw"; + +static const char *tgsi_file_names[PROGRAM_FILE_MAX] = { + "TEMP", "ARRAY", "IN", "OUT", "STATE", "CONST", + "UNIFORM", "WO", "ADDR", "SAMPLER", "SV", "UNDEF", + "IMM", "BUF", "MEM", "IMAGE" +}; + +static +void dump_instruction(int line, prog_scope *scope, + const glsl_to_tgsi_instruction& inst) +{ + const struct tgsi_opcode_info *info = tgsi_get_opcode_info(inst.op); + + int indent = scope->nesting_depth(); + if ((scope->type() == switch_case_branch || + scope->type() == switch_default_branch) && + (info->opcode == TGSI_OPCODE_CASE || + info->opcode == TGSI_OPCODE_DEFAULT)) + --indent; + + if (info->opcode == TGSI_OPCODE_ENDIF || + info->opcode == TGSI_OPCODE_ELSE || + info->opcode == TGSI_OPCODE_ENDLOOP || + info->opcode == TGSI_OPCODE_ENDSWITCH) + --indent; + + cerr << setw(4) << line << ": "; + for (int i = 0; i < indent; ++i) + cerr << " "; + cerr << tgsi_get_opcode_name(info->opcode) << " "; + + bool has_operators = false; + for (unsigned j = 0; j < num_inst_dst_regs(&inst); j++) { + has_operators = true; + if (j > 0) + cerr << ", "; + + const st_dst_reg& dst = inst.dst[j]; + cerr << tgsi_file_names[dst.file]; + + if (dst.file == PROGRAM_ARRAY) + cerr << "(" << dst.array_id << ")"; + + cerr << "[" << dst.index << "]"; + + if (dst.writemask != TGSI_WRITEMASK_XYZW) { + cerr << "."; + if (dst.writemask & TGSI_WRITEMASK_X) cerr << "x"; + if (dst.writemask & TGSI_WRITEMASK_Y) cerr << "y"; + if (dst.writemask & TGSI_WRITEMASK_Z) cerr << "z"; + if (dst.writemask & TGSI_WRITEMASK_W) cerr << "w"; + } + } + if (has_operators) + cerr << " := "; + + for (unsigned j = 0; j < num_inst_src_regs(&inst); j++) { + if (j > 0) + cerr << ", "; + + const st_src_reg& src = inst.src[j]; + cerr << tgsi_file_names[src.file] + << "[" << src.index << "]"; + if (src.swizzle != SWIZZLE_XYZW) { + cerr << "."; + for (int idx = 0; idx < 4; ++idx) { + int swz = GET_SWZ(src.swizzle, idx); + if (swz < 4) { + cerr << swizzle_txt[swz]; + } + } + } + } + + if (inst.tex_offset_num_offset > 0) { + cerr << ", TEXOFS: "; + for (unsigned j = 0; j < inst.tex_offset_num_offset; j++) { + if (j > 0) + cerr << ", "; + + const st_src_reg& src = inst.tex_offsets[j]; + cerr << tgsi_file_names[src.file] + << "[" << src.index << "]"; + if (src.swizzle != SWIZZLE_XYZW) { + cerr << "."; + for (int idx = 0; idx < 4; ++idx) { + int swz = GET_SWZ(src.swizzle, idx); + if (swz < 4) { + cerr << swizzle_txt[swz]; + } + } + } + } + } + cerr << "\n"; +} +#endif diff --git a/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.h b/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.h new file mode 100644 index 000000000..3f21b1317 --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/st_glsl_to_tgsi_temprename.h @@ -0,0 +1,71 @@ +/* + * Copyright © 2017 Gert Wollny + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 MESA_GLSL_TO_TGSI_TEMPRENAME_H +#define MESA_GLSL_TO_TGSI_TEMPRENAME_H + +#include "st_glsl_to_tgsi_private.h" + +/** Storage to record the required life time of a temporary register + * begin == end == -1 indicates that the register can be reused without + * limitations. Otherwise, "begin" indicates the first instruction in which + * a write operation may target this temporary, and end indicates the + * last instruction in which a value can be read from this temporary. + * Hence, a register R2 can be merged with a register R1 if R1.end <= R2.begin. + */ +struct lifetime { + int begin; + int end; +}; + +/** Evaluates the required life times of temporary registers in a shader. + * The life time estimation can only be run sucessfully if the shader doesn't + * call a subroutine. + * @param[in] mem_ctx a memory context that can be used with the ralloc_* functions + * @param[in] instructions the shader to be anlzyed + * @param[in] ntemps number of temporaries reserved for this shader + * @param[in,out] lifetimes memory location to store the estimated required + * life times for each temporary register. The parameter must point to + * allocated memory that can hold ntemps lifetime structures. On output + * the life times contains the life times for the registers with the + * exception of TEMP[0]. + * @returns: true if the lifetimes were estimated, false if not (i.e. if a + * subroutine was called). + */ +bool +get_temp_registers_required_lifetimes(void *mem_ctx, exec_list *instructions, + int ntemps, struct lifetime *lifetimes); +/** Estimate the merge remapping of the registers. + * @param[in] mem_ctx a memory context that can be used with the ralloc_* functions + * @param[in] ntemps number of temporaries reserved for this shader + * @param[in] lifetimes required life time for each temporary register. + * @param[in,out] result memory location to store the register remapping table. + * On input the parameter must point to allocated memory that can hold the + * renaming information for ntemps registers, on output the mapping is stored. + * Note that TEMP[0] is not considered for register renaming. + */ +void get_temp_registers_remapping(void *mem_ctx, int ntemps, + const struct lifetime* lifetimes, + struct rename_reg_pair *result); + +#endif
\ No newline at end of file diff --git a/lib/mesa/src/mesa/state_tracker/st_glsl_types.h b/lib/mesa/src/mesa/state_tracker/st_glsl_types.h index 3a39ceefe..915816d1f 100644 --- a/lib/mesa/src/mesa/state_tracker/st_glsl_types.h +++ b/lib/mesa/src/mesa/state_tracker/st_glsl_types.h @@ -33,8 +33,8 @@ extern "C" { #endif -int st_glsl_attrib_type_size(const struct glsl_type *type, bool is_vs_input); -int st_glsl_type_size(const struct glsl_type *type); +int st_glsl_storage_type_size(const struct glsl_type *type, + bool is_bindless); #ifdef __cplusplus diff --git a/lib/mesa/src/mesa/state_tracker/st_vdpau.c b/lib/mesa/src/mesa/state_tracker/st_vdpau.c index 027381530..19611e719 100644 --- a/lib/mesa/src/mesa/state_tracker/st_vdpau.c +++ b/lib/mesa/src/mesa/state_tracker/st_vdpau.c @@ -221,7 +221,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, /* switch to surface based */ if (!stObj->surface_based) { - _mesa_clear_texture_object(ctx, texObj); + _mesa_clear_texture_object(ctx, texObj, NULL); stObj->surface_based = GL_TRUE; } @@ -236,6 +236,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, pipe_resource_reference(&stImage->pt, res); stObj->surface_format = res->format; + stObj->level_override = 0; stObj->layer_override = layer_override; _mesa_dirty_texobj(ctx, texObj); @@ -256,6 +257,7 @@ st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access, st_texture_release_all_sampler_views(st, stObj); pipe_resource_reference(&stImage->pt, NULL); + stObj->level_override = 0; stObj->layer_override = 0; _mesa_dirty_texobj(ctx, texObj); diff --git a/lib/mesa/src/mesa/state_tracker/tests/Makefile.am b/lib/mesa/src/mesa/state_tracker/tests/Makefile.am new file mode 100644 index 000000000..f32957608 --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/tests/Makefile.am @@ -0,0 +1,34 @@ +include $(top_srcdir)/src/gallium/Automake.inc + +AM_CFLAGS = \ + $(PTHREAD_CFLAGS) + +AM_CXXFLAGS = \ + $(GALLIUM_DRIVER_CXXFLAGS) \ + -std=c++11 + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/gtest/include \ + -I$(top_srcdir)/src/mapi \ + -I$(top_builddir)/src/mesa \ + -I$(top_srcdir)/src/mesa \ + -I$(top_builddir)/src/compiler/glsl \ + $(DEFINES) + +TESTS = st-renumerate-test +check_PROGRAMS = st-renumerate-test + +st_renumerate_test_SOURCES = \ + test_glsl_to_tgsi_lifetime.cpp + +st_renumerate_test_LDFLAGS = \ + $(LLVM_LDFLAGS) + +st_renumerate_test_LDADD = \ + $(top_builddir)/src/mesa/libmesagallium.la \ + $(top_builddir)/src/mapi/shared-glapi/libglapi.la \ + $(top_builddir)/src/gallium/auxiliary/libgallium.la \ + $(top_builddir)/src/util/libmesautil.la \ + $(top_builddir)/src/gtest/libgtest.la \ + $(GALLIUM_COMMON_LIB_DEPS) \ + $(LLVM_LIBS) diff --git a/lib/mesa/src/mesa/state_tracker/tests/Makefile.in b/lib/mesa/src/mesa/state_tracker/tests/Makefile.in new file mode 100644 index 000000000..6b9c67a3a --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/tests/Makefile.in @@ -0,0 +1,1266 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@HAVE_LIBDRM_TRUE@am__append_1 = \ +@HAVE_LIBDRM_TRUE@ $(LIBDRM_LIBS) + +@HAVE_DRISW_TRUE@am__append_2 = \ +@HAVE_DRISW_TRUE@ $(top_builddir)/src/gallium/winsys/sw/dri/libswdri.la + +@HAVE_DRISW_KMS_TRUE@am__append_3 = \ +@HAVE_DRISW_KMS_TRUE@ $(top_builddir)/src/gallium/winsys/sw/kms-dri/libswkmsdri.la \ +@HAVE_DRISW_KMS_TRUE@ $(LIBDRM_LIBS) + +TESTS = st-renumerate-test$(EXEEXT) +check_PROGRAMS = st-renumerate-test$(EXEEXT) +subdir = src/mesa/state_tracker/tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_gnu_make.m4 \ + $(top_srcdir)/m4/ax_check_python_mako_module.m4 \ + $(top_srcdir)/m4/ax_gcc_builtin.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_prog_bison.m4 \ + $(top_srcdir)/m4/ax_prog_flex.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/VERSION $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am_st_renumerate_test_OBJECTS = test_glsl_to_tgsi_lifetime.$(OBJEXT) +st_renumerate_test_OBJECTS = $(am_st_renumerate_test_OBJECTS) +am__DEPENDENCIES_1 = +@HAVE_LIBDRM_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) +am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) +st_renumerate_test_DEPENDENCIES = \ + $(top_builddir)/src/mesa/libmesagallium.la \ + $(top_builddir)/src/mapi/shared-glapi/libglapi.la \ + $(top_builddir)/src/gallium/auxiliary/libgallium.la \ + $(top_builddir)/src/util/libmesautil.la \ + $(top_builddir)/src/gtest/libgtest.la $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +st_renumerate_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(st_renumerate_test_LDFLAGS) \ + $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/bin/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(st_renumerate_test_SOURCES) +DIST_SOURCES = $(st_renumerate_test_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/bin/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/bin/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/bin/depcomp \ + $(top_srcdir)/bin/test-driver \ + $(top_srcdir)/src/gallium/Automake.inc +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDGPU_CFLAGS = @AMDGPU_CFLAGS@ +AMDGPU_LIBS = @AMDGPU_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ANDROID_CFLAGS = @ANDROID_CFLAGS@ +ANDROID_LIBS = @ANDROID_LIBS@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BSYMBOLIC = @BSYMBOLIC@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLANG_RESOURCE_DIR = @CLANG_RESOURCE_DIR@ +CLOCK_LIB = @CLOCK_LIB@ +CLOVER_STD_OVERRIDE = @CLOVER_STD_OVERRIDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +D3D_DRIVER_INSTALL_DIR = @D3D_DRIVER_INSTALL_DIR@ +DEFINES = @DEFINES@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ +DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRIGL_CFLAGS = @DRIGL_CFLAGS@ +DRIGL_LIBS = @DRIGL_LIBS@ +DRI_DRIVER_INSTALL_DIR = @DRI_DRIVER_INSTALL_DIR@ +DRI_DRIVER_SEARCH_DIR = @DRI_DRIVER_SEARCH_DIR@ +DRI_LIB_DEPS = @DRI_LIB_DEPS@ +DRI_PC_REQ_PRIV = @DRI_PC_REQ_PRIV@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGL_CFLAGS = @EGL_CFLAGS@ +EGL_LIB_DEPS = @EGL_LIB_DEPS@ +EGL_NATIVE_PLATFORM = @EGL_NATIVE_PLATFORM@ +EGREP = @EGREP@ +ETNAVIV_CFLAGS = @ETNAVIV_CFLAGS@ +ETNAVIV_LIBS = @ETNAVIV_LIBS@ +EXEEXT = @EXEEXT@ +EXPAT_CFLAGS = @EXPAT_CFLAGS@ +EXPAT_LIBS = @EXPAT_LIBS@ +FGREP = @FGREP@ +FREEDRENO_CFLAGS = @FREEDRENO_CFLAGS@ +FREEDRENO_LIBS = @FREEDRENO_LIBS@ +GALLIUM_PIPE_LOADER_DEFINES = @GALLIUM_PIPE_LOADER_DEFINES@ +GBM_PC_LIB_PRIV = @GBM_PC_LIB_PRIV@ +GBM_PC_REQ_PRIV = @GBM_PC_REQ_PRIV@ +GC_SECTIONS = @GC_SECTIONS@ +GLESv1_CM_LIB_DEPS = @GLESv1_CM_LIB_DEPS@ +GLESv1_CM_PC_LIB_PRIV = @GLESv1_CM_PC_LIB_PRIV@ +GLESv2_LIB_DEPS = @GLESv2_LIB_DEPS@ +GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@ +GLPROTO_CFLAGS = @GLPROTO_CFLAGS@ +GLPROTO_LIBS = @GLPROTO_LIBS@ +GLVND_CFLAGS = @GLVND_CFLAGS@ +GLVND_LIBS = @GLVND_LIBS@ +GLX_TLS = @GLX_TLS@ +GL_LIB = @GL_LIB@ +GL_LIB_DEPS = @GL_LIB_DEPS@ +GL_PC_CFLAGS = @GL_PC_CFLAGS@ +GL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@ +GL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@ +GREP = @GREP@ +HAVE_XF86VIDMODE = @HAVE_XF86VIDMODE@ +I915_CFLAGS = @I915_CFLAGS@ +I915_LIBS = @I915_LIBS@ +INDENT = @INDENT@ +INDENT_FLAGS = @INDENT_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LD_NO_UNDEFINED = @LD_NO_UNDEFINED@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBATOMIC_LIBS = @LIBATOMIC_LIBS@ +LIBCLC_INCLUDEDIR = @LIBCLC_INCLUDEDIR@ +LIBCLC_LIBEXECDIR = @LIBCLC_LIBEXECDIR@ +LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ +LIBDRM_LIBS = @LIBDRM_LIBS@ +LIBELF_CFLAGS = @LIBELF_CFLAGS@ +LIBELF_LIBS = @LIBELF_LIBS@ +LIBGLVND_DATADIR = @LIBGLVND_DATADIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSENSORS_LIBS = @LIBSENSORS_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIB_DIR = @LIB_DIR@ +LIB_EXT = @LIB_EXT@ +LIPO = @LIPO@ +LLVM_CFLAGS = @LLVM_CFLAGS@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_CXXFLAGS = @LLVM_CXXFLAGS@ +LLVM_INCLUDEDIR = @LLVM_INCLUDEDIR@ +LLVM_LDFLAGS = @LLVM_LDFLAGS@ +LLVM_LIBS = @LLVM_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSVC2013_COMPAT_CFLAGS = @MSVC2013_COMPAT_CFLAGS@ +MSVC2013_COMPAT_CXXFLAGS = @MSVC2013_COMPAT_CXXFLAGS@ +NINE_MAJOR = @NINE_MAJOR@ +NINE_MINOR = @NINE_MINOR@ +NINE_TINY = @NINE_TINY@ +NINE_VERSION = @NINE_VERSION@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NOUVEAU_CFLAGS = @NOUVEAU_CFLAGS@ +NOUVEAU_LIBS = @NOUVEAU_LIBS@ +NVVIEUX_CFLAGS = @NVVIEUX_CFLAGS@ +NVVIEUX_LIBS = @NVVIEUX_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OMX_BELLAGIO_CFLAGS = @OMX_BELLAGIO_CFLAGS@ +OMX_BELLAGIO_LIBS = @OMX_BELLAGIO_LIBS@ +OMX_BELLAGIO_LIB_INSTALL_DIR = @OMX_BELLAGIO_LIB_INSTALL_DIR@ +OPENCL_LIBNAME = @OPENCL_LIBNAME@ +OPENCL_VERSION = @OPENCL_VERSION@ +OSMESA_LIB = @OSMESA_LIB@ +OSMESA_LIB_DEPS = @OSMESA_LIB_DEPS@ +OSMESA_PC_LIB_PRIV = @OSMESA_PC_LIB_PRIV@ +OSMESA_PC_REQ = @OSMESA_PC_REQ@ +OSMESA_VERSION = @OSMESA_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSIX_SHELL = @POSIX_SHELL@ +PTHREADSTUBS_CFLAGS = @PTHREADSTUBS_CFLAGS@ +PTHREADSTUBS_LIBS = @PTHREADSTUBS_LIBS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PWR8_CFLAGS = @PWR8_CFLAGS@ +PYTHON2 = @PYTHON2@ +RADEON_CFLAGS = @RADEON_CFLAGS@ +RADEON_LIBS = @RADEON_LIBS@ +RANLIB = @RANLIB@ +RM = @RM@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIMPENROSE_CFLAGS = @SIMPENROSE_CFLAGS@ +SIMPENROSE_LIBS = @SIMPENROSE_LIBS@ +SSE41_CFLAGS = @SSE41_CFLAGS@ +STRIP = @STRIP@ +SWR_AVX2_CXXFLAGS = @SWR_AVX2_CXXFLAGS@ +SWR_AVX_CXXFLAGS = @SWR_AVX_CXXFLAGS@ +SWR_CXX11_CXXFLAGS = @SWR_CXX11_CXXFLAGS@ +SWR_KNL_CXXFLAGS = @SWR_KNL_CXXFLAGS@ +SWR_SKX_CXXFLAGS = @SWR_SKX_CXXFLAGS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VA_CFLAGS = @VA_CFLAGS@ +VA_LIBS = @VA_LIBS@ +VA_LIB_INSTALL_DIR = @VA_LIB_INSTALL_DIR@ +VA_MAJOR = @VA_MAJOR@ +VA_MINOR = @VA_MINOR@ +VC5_SIMULATOR_CFLAGS = @VC5_SIMULATOR_CFLAGS@ +VC5_SIMULATOR_LIBS = @VC5_SIMULATOR_LIBS@ +VDPAU_CFLAGS = @VDPAU_CFLAGS@ +VDPAU_LIBS = @VDPAU_LIBS@ +VDPAU_LIB_INSTALL_DIR = @VDPAU_LIB_INSTALL_DIR@ +VDPAU_MAJOR = @VDPAU_MAJOR@ +VDPAU_MINOR = @VDPAU_MINOR@ +VERSION = @VERSION@ +VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@ +VISIBILITY_CXXFLAGS = @VISIBILITY_CXXFLAGS@ +VL_CFLAGS = @VL_CFLAGS@ +VL_LIBS = @VL_LIBS@ +VULKAN_ICD_INSTALL_DIR = @VULKAN_ICD_INSTALL_DIR@ +WAYLAND_CLIENT_CFLAGS = @WAYLAND_CLIENT_CFLAGS@ +WAYLAND_CLIENT_LIBS = @WAYLAND_CLIENT_LIBS@ +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ +WAYLAND_SCANNER_CFLAGS = @WAYLAND_SCANNER_CFLAGS@ +WAYLAND_SCANNER_LIBS = @WAYLAND_SCANNER_LIBS@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WNO_OVERRIDE_INIT = @WNO_OVERRIDE_INIT@ +X11_INCLUDES = @X11_INCLUDES@ +XA_MAJOR = @XA_MAJOR@ +XA_MINOR = @XA_MINOR@ +XA_TINY = @XA_TINY@ +XA_VERSION = @XA_VERSION@ +XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@ +XCB_DRI2_LIBS = @XCB_DRI2_LIBS@ +XCB_DRI3_CFLAGS = @XCB_DRI3_CFLAGS@ +XCB_DRI3_LIBS = @XCB_DRI3_LIBS@ +XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ +XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ +XLIBGL_CFLAGS = @XLIBGL_CFLAGS@ +XLIBGL_LIBS = @XLIBGL_LIBS@ +XVMC_CFLAGS = @XVMC_CFLAGS@ +XVMC_LIBS = @XVMC_LIBS@ +XVMC_LIB_INSTALL_DIR = @XVMC_LIB_INSTALL_DIR@ +XVMC_MAJOR = @XVMC_MAJOR@ +XVMC_MINOR = @XVMC_MINOR@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acv_mako_found = @acv_mako_found@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ifGNUmake = @ifGNUmake@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +GALLIUM_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + $(DEFINES) + + +# src/gallium/auxiliary must appear before src/gallium/drivers +# because there are stupidly two rbug_context.h files in +# different directories, and which one is included by the +# preprocessor is determined by the ordering of the -I flags. +GALLIUM_DRIVER_CFLAGS = \ + -I$(srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + -I$(top_srcdir)/src/gallium/drivers \ + -I$(top_srcdir)/src/gallium/winsys \ + $(DEFINES) \ + $(VISIBILITY_CFLAGS) + +GALLIUM_DRIVER_CXXFLAGS = \ + -I$(srcdir)/include \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + -I$(top_srcdir)/src/gallium/drivers \ + -I$(top_srcdir)/src/gallium/winsys \ + $(DEFINES) \ + $(VISIBILITY_CXXFLAGS) + +GALLIUM_TARGET_CFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/loader \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + -I$(top_srcdir)/src/gallium/drivers \ + -I$(top_srcdir)/src/gallium/winsys \ + -I$(top_builddir)/src/util/ \ + -I$(top_builddir)/src/gallium/drivers/ \ + $(DEFINES) \ + $(PTHREAD_CFLAGS) \ + $(LIBDRM_CFLAGS) \ + $(VISIBILITY_CFLAGS) + +GALLIUM_COMMON_LIB_DEPS = -lm $(LIBUNWIND_LIBS) $(LIBSENSORS_LIBS) \ + $(CLOCK_LIB) $(PTHREAD_LIBS) $(DLOPEN_LIBS) $(am__append_1) +GALLIUM_WINSYS_CFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gallium/include \ + -I$(top_srcdir)/src/gallium/auxiliary \ + $(DEFINES) \ + $(VISIBILITY_CFLAGS) + +GALLIUM_PIPE_LOADER_WINSYS_LIBS = \ + $(top_builddir)/src/gallium/winsys/sw/null/libws_null.la \ + $(top_builddir)/src/gallium/winsys/sw/wrapper/libwsw.la \ + $(am__append_2) $(am__append_3) +AM_CFLAGS = \ + $(PTHREAD_CFLAGS) + +AM_CXXFLAGS = \ + $(GALLIUM_DRIVER_CXXFLAGS) \ + -std=c++11 + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/gtest/include \ + -I$(top_srcdir)/src/mapi \ + -I$(top_builddir)/src/mesa \ + -I$(top_srcdir)/src/mesa \ + -I$(top_builddir)/src/compiler/glsl \ + $(DEFINES) + +st_renumerate_test_SOURCES = \ + test_glsl_to_tgsi_lifetime.cpp + +st_renumerate_test_LDFLAGS = \ + $(LLVM_LDFLAGS) + +st_renumerate_test_LDADD = \ + $(top_builddir)/src/mesa/libmesagallium.la \ + $(top_builddir)/src/mapi/shared-glapi/libglapi.la \ + $(top_builddir)/src/gallium/auxiliary/libgallium.la \ + $(top_builddir)/src/util/libmesautil.la \ + $(top_builddir)/src/gtest/libgtest.la \ + $(GALLIUM_COMMON_LIB_DEPS) \ + $(LLVM_LIBS) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/src/gallium/Automake.inc $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/mesa/state_tracker/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/mesa/state_tracker/tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; +$(top_srcdir)/src/gallium/Automake.inc $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +st-renumerate-test$(EXEEXT): $(st_renumerate_test_OBJECTS) $(st_renumerate_test_DEPENDENCIES) $(EXTRA_st_renumerate_test_DEPENDENCIES) + @rm -f st-renumerate-test$(EXEEXT) + $(AM_V_CXXLD)$(st_renumerate_test_LINK) $(st_renumerate_test_OBJECTS) $(st_renumerate_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_glsl_to_tgsi_lifetime.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +st-renumerate-test.log: st-renumerate-test$(EXEEXT) + @p='st-renumerate-test$(EXEEXT)'; \ + b='st-renumerate-test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/mesa/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp b/lib/mesa/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp new file mode 100644 index 000000000..93f4020eb --- /dev/null +++ b/lib/mesa/src/mesa/state_tracker/tests/test_glsl_to_tgsi_lifetime.cpp @@ -0,0 +1,1600 @@ +/* + * Copyright © 2017 Gert Wollny + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <state_tracker/st_glsl_to_tgsi_temprename.h> +#include <tgsi/tgsi_ureg.h> +#include <tgsi/tgsi_info.h> +#include <compiler/glsl/list.h> +#include <mesa/program/prog_instruction.h> + +#include <utility> +#include <gtest/gtest.h> + +using std::vector; +using std::pair; +using std::make_pair; + +/* A line to describe a TGSI instruction for building mock shaders. */ +struct MockCodeline { + MockCodeline(unsigned _op): op(_op) {} + MockCodeline(unsigned _op, const vector<int>& _dst, const vector<int>& _src, const vector<int>&_to): + op(_op), dst(_dst), src(_src), tex_offsets(_to){} + unsigned op; + vector<int> dst; + vector<int> src; + vector<int> tex_offsets; +}; + +/* A line to describe a TGSI instruction with swizzeling and write makss + * for building mock shaders. + */ +struct MockCodelineWithSwizzle { + MockCodelineWithSwizzle(unsigned _op): op(_op) {} + MockCodelineWithSwizzle(unsigned _op, const vector<pair<int,int>>& _dst, + const vector<pair<int, const char *>>& _src, + const vector<pair<int, const char *>>&_to): + op(_op), dst(_dst), src(_src), tex_offsets(_to){} + unsigned op; + vector<pair<int,int>> dst; + vector<pair<int, const char *>> src; + vector<pair<int, const char *>> tex_offsets; +}; + +/* A few constants that will notbe tracked as temporary registers by the + * mock shader. + */ +const int in0 = -1; +const int in1 = -2; +const int in2 = -3; + +const int out0 = -1; +const int out1 = -2; + +class MockShader { +public: + MockShader(const vector<MockCodeline>& source); + MockShader(const vector<MockCodelineWithSwizzle>& source); + ~MockShader(); + + void free(); + + exec_list* get_program() const; + int get_num_temps() const; +private: + st_src_reg create_src_register(int src_idx); + st_dst_reg create_dst_register(int dst_idx); + st_src_reg create_src_register(int src_idx, const char *swizzle); + st_dst_reg create_dst_register(int dst_idx,int writemask); + exec_list* program; + int num_temps; + void *mem_ctx; +}; + +using expectation = vector<vector<int>>; + +class MesaTestWithMemCtx : public testing::Test { + void SetUp(); + void TearDown(); +protected: + void *mem_ctx; +}; + +class LifetimeEvaluatorTest : public MesaTestWithMemCtx { +protected: + void run(const vector<MockCodeline>& code, const expectation& e); + void run(const vector<MockCodelineWithSwizzle>& code, const expectation& e); +private: + virtual void check(const vector<lifetime>& result, const expectation& e) = 0; +}; + +/* This is a test class to check the exact life times of + * registers. */ +class LifetimeEvaluatorExactTest : public LifetimeEvaluatorTest { +protected: + void check(const vector<lifetime>& result, const expectation& e); +}; + +/* This test class checks that the life time covers at least + * in the expected range. It is used for cases where we know that + * a the implementation could be improved on estimating the minimal + * life time. + */ +class LifetimeEvaluatorAtLeastTest : public LifetimeEvaluatorTest { +protected: + void check(const vector<lifetime>& result, const expectation& e); +}; + +/* With this test class the renaming mapping estimation is tested */ +class RegisterRemappingTest : public MesaTestWithMemCtx { +protected: + void run(const vector<lifetime>& lt, const vector<int>& expect); +}; + +/* With this test class the combined lifetime estimation and renaming + * mepping estimation is tested + */ +class RegisterLifetimeAndRemappingTest : public RegisterRemappingTest { +protected: + using RegisterRemappingTest::run; + template <typename CodeLine> + void run(const vector<CodeLine>& code, const vector<int>& expect); +}; + +template <typename CodeLine> +void RegisterLifetimeAndRemappingTest::run(const vector<CodeLine>& code, + const vector<int>& expect) +{ + MockShader shader(code); + std::vector<lifetime> lt(shader.get_num_temps()); + get_temp_registers_required_lifetimes(mem_ctx, shader.get_program(), + shader.get_num_temps(), <[0]); + this->run(lt, expect); +} + +TEST_F(LifetimeEvaluatorExactTest, SimpleMoveAdd) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_UADD, {out0}, {1,in0}, {}}, + { TGSI_OPCODE_END} + }; + run(code, expectation({{-1,-1}, {0,1}})); +} + +TEST_F(LifetimeEvaluatorExactTest, SimpleMoveAddMove) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run(code, expectation({{-1, -1}, {0,1}, {1,2}})); +} + +/* Test whether the texoffst are actually visited by the + * merge algorithm. Note that it is of no importance + * what instruction is actually used, the MockShader class + * does not consider the details of the operation, only + * the number of arguments is of importance. + */ +TEST_F(LifetimeEvaluatorExactTest, SimpleOpWithTexoffset) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {2}, {in1}, {}}, + { TGSI_OPCODE_TEX, {out0}, {in0}, {1,2}}, + { TGSI_OPCODE_END} + }; + run(code, expectation({{-1, -1}, {0,2}, {1,2}})); +} + +/* Simple register access involving a loop + * 1: must life up to then end of the loop + * 2: only needs to life from write to read + * 3: only needs to life from write to read outside the loop + */ +TEST_F(LifetimeEvaluatorExactTest, SimpleMoveInLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_UADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_UADD, {3}, {3,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {3}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,5}, {2,3}, {3,6}})); +} + +/* In loop if/else value written only in one path, and read later + * - value must survive the whole loop. + */ +TEST_F(LifetimeEvaluatorExactTest, MoveInIfInLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in1}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_UADD, {3}, {3,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {3}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,7}, {1,7}, {5,8}})); +} + +/* A non-dominant write within an IF can be ignored (if it is read + * later) + */ +TEST_F(LifetimeEvaluatorExactTest, NonDominantWriteinIfInLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in1}, {}}, + { TGSI_OPCODE_MOV, {1}, {in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {2}, {1,in1}, {}}, + { TGSI_OPCODE_IF, {}, {2}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {1,5}, {5,10}})); +} + +/* In Nested loop if/else value written only in one path, and read later + * - value must survive the outer loop. + */ +TEST_F(LifetimeEvaluatorExactTest, MoveInIfInNestedLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in1}, {} }, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {3}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,8}, {1,8}, {6,9}})); +} + +/* In loop if/else value written in both path, and read later + * - value must survive from first write to last read in loop + * for now we only check that the minimum life time is correct. + */ +TEST_F(LifetimeEvaluatorAtLeastTest, WriteInIfAndElseInLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ELSE }, + { TGSI_OPCODE_MOV, {2}, {1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_UADD, {3}, {3,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {3}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,9}, {3,7}, {7,10}})); +} + +/* In loop if/else value written in both path, read in else path + * before write and also read later + * - value must survive the whole loop + */ +TEST_F(LifetimeEvaluatorExactTest, WriteInIfAndElseReadInElseInLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,in0}, {}}, + { TGSI_OPCODE_ELSE }, + { TGSI_OPCODE_ADD, {2}, {1,2}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_UADD, {3}, {3,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {3}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,9}, {1,9}, {7,10}})); +} + +/* In loop if/else read in one path before written in the same loop + * - value must survive the whole loop + */ +TEST_F(LifetimeEvaluatorExactTest, ReadInIfInLoopBeforeWrite) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_UADD, {2}, {1,3}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_UADD, {3}, {3,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {3}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,7}, {1,7}, {1,8}})); +} + +/* In loop if/else read in one path before written in the same loop + * read after the loop, value must survivethe whole loop and + * to the read. + */ +TEST_F(LifetimeEvaluatorExactTest, ReadInLoopInIfBeforeWriteAndLifeToTheEnd) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MUL, {1}, {1,in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_UADD, {1}, {1,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,6}})); +} + +/* In loop if/else read in one path before written in the same loop + * read after the loop, value must survivethe whole loop and + * to the read. + */ +TEST_F(LifetimeEvaluatorExactTest, ReadInLoopBeforeWriteAndLifeToTheEnd) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_MUL, {1}, {1,in1}, {}}, + { TGSI_OPCODE_UADD, {1}, {1,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,4}})); +} + + +/* Write in nested ifs in loop, for now we do test whether the + * life time is at least what is required, but we know that the + * implementation doesn't do a full check and sets larger boundaries + */ +TEST_F(LifetimeEvaluatorAtLeastTest, NestedIfInLoopAlwaysWriteButNotPropagated) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {3,14}})); +} + +/* The value is written in a loop and in a nested if, but + * not in all code paths, hence the value must survive the loop. + */ +TEST_F(LifetimeEvaluatorExactTest, NestedIfInLoopWriteNotAlways) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,13}})); +} + +/* A continue in the loop is not relevant */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterContinue) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_CONT}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {4,6}})); +} + +/* Temporary used to in case must live up to the case + * statement where it is used, the switch we only keep + * for the actual SWITCH opcode like it is in tgsi_exec.c, the + * only current use case. + */ +TEST_F(LifetimeEvaluatorExactTest, UseSwitchCase) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {2}, {in1}, {}}, + { TGSI_OPCODE_MOV, {3}, {in2}, {}}, + { TGSI_OPCODE_SWITCH, {}, {3}, {}}, + { TGSI_OPCODE_CASE, {}, {2}, {}}, + { TGSI_OPCODE_CASE, {}, {1}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_DEFAULT}, + { TGSI_OPCODE_ENDSWITCH}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,5}, {1,4}, {2,3}})); +} + +/* With two destinations, if one result is thrown away, the + * register must be kept past the writing instructions. + */ +TEST_F(LifetimeEvaluatorExactTest, WriteTwoOnlyUseOne) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_DFRACEXP , {1,2}, {in0}, {}}, + { TGSI_OPCODE_ADD , {3}, {2,in0}, {}}, + { TGSI_OPCODE_MOV, {out1}, {3}, {}}, + { TGSI_OPCODE_END}, + + }; + run (code, expectation({{-1,-1}, {0,1}, {0,1}, {1,2}})); +} + +/* If a break is in the loop, all variables written after the + * break and used outside the loop must be maintained for the + * whole loop + */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterBreak) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,6}})); +} + +/* If a break is in the loop, all variables written after the + * break and used outside the loop must be maintained for the + * whole loop. The first break in the loop is the defining one. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterBreak2Breaks) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,7}})); +} + +/* Loop with a break at the beginning and read/write in the post + * break loop scope. The value written and read within the loop + * can be limited to [write, read], but the value read outside the + * loop must survive the whole loop. This is the typical code for + * while and for loops, where the breaking condition is tested at + * the beginning. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAndReadAfterBreak) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {2}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {4,5}, {0,7}})); +} + +/* Same as above, just make sure that the life time of the local variable + * in the outer loop (3) is not accidently promoted to the whole loop. + */ +TEST_F(LifetimeEvaluatorExactTest, NestedLoopWithWriteAndReadAfterBreak) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in1}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_BGNLOOP}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {2}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_ADD, {3}, {2,in0}, {}}, + { TGSI_OPCODE_ADD, {4}, {3,in2}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {4}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {8,9}, {0,13}, {11,12}, {0,14}})); +} + +/* If a break is in the loop inside a switch case, make sure it is + * interpreted as breaking that inner loop, i.e. the variable has to + * survive the loop. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteAfterBreakInSwitchInLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_SWITCH, {}, {in1}, {}}, + { TGSI_OPCODE_CASE, {}, {in1}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_DEFAULT, {}, {}, {}}, + { TGSI_OPCODE_ENDSWITCH, {}, {}, {}}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {2,10}})); +} + +/* Value written conditionally in one loop and read in another loop, + * and both of these loops are within yet another loop. Here the value + * has to survive the outer loop. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopsWithDifferntScopesConditionalWrite) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,7}})); +} + +/* Value written and read in one loop and last read in another loop, + * Here the value has to survive both loops. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopsWithDifferntScopesFirstReadBeforeWrite) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_MUL, {1}, {1,in0}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,5}})); +} + + +/* Value is written in one switch code path within a loop + * must survive the full loop. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithWriteInSwitch) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_SWITCH, {}, {in0}, {} }, + { TGSI_OPCODE_CASE, {}, {in0}, {} }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_DEFAULT }, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_ENDSWITCH }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,9}})); +} + +/* Value written in one case, and read in other,in loop + * - must survive the loop. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithReadWriteInSwitchDifferentCase) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_SWITCH, {}, {in0}, {} }, + { TGSI_OPCODE_CASE, {}, {in0}, {} }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_DEFAULT }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_ENDSWITCH }, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,9}})); +} + +/* Value written in one case, and read in other,in loop + * - must survive the loop, even if the write case falls through. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithReadWriteInSwitchDifferentCaseFallThrough) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_SWITCH, {}, {in0}, {} }, + { TGSI_OPCODE_CASE, {}, {in0}, {} }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_DEFAULT }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_ENDSWITCH }, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,8}})); +} + + +/* Here we read and write from an to the same temp in the same instruction, + * but the read is conditional (select operation), hence the lifetime must + * start with the first write. + */ +TEST_F(LifetimeEvaluatorExactTest, WriteSelectFromSelf) +{ + const vector<MockCodeline> code = { + {TGSI_OPCODE_USEQ, {5}, {in0,in1}, {}}, + {TGSI_OPCODE_UCMP, {1}, {5,in1,1}, {}}, + {TGSI_OPCODE_UCMP, {1}, {5,in1,1}, {}}, + {TGSI_OPCODE_UCMP, {1}, {5,in1,1}, {}}, + {TGSI_OPCODE_UCMP, {1}, {5,in1,1}, {}}, + {TGSI_OPCODE_FSLT, {2}, {1,in1}, {}}, + {TGSI_OPCODE_UIF, {}, {2}, {}}, + { TGSI_OPCODE_MOV, {3}, {in1}, {}}, + {TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {4}, {in1}, {}}, + { TGSI_OPCODE_MOV, {4}, {4}, {}}, + { TGSI_OPCODE_MOV, {3}, {4}, {}}, + {TGSI_OPCODE_ENDIF}, + {TGSI_OPCODE_MOV, {out1}, {3}, {}}, + {TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {1,5}, {5,6}, {7,13}, {9,11}, {0,4}})); +} + +/* This test checks wheter the ENDSWITCH is handled properly if the + * last switch case/default doesn't stop with a BRK. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopRWInSwitchCaseLastCaseWithoutBreak) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_SWITCH, {}, {in0}, {} }, + { TGSI_OPCODE_CASE, {}, {in0}, {} }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_DEFAULT }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDSWITCH }, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,8}})); +} + +/* Value read/write in same case, stays there */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithReadWriteInSwitchSameCase) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_SWITCH, {}, {in0}, {} }, + { TGSI_OPCODE_CASE, {}, {in0}, {} }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_DEFAULT }, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_ENDSWITCH }, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {3,4}})); +} + +/* Value read/write in all cases, should only live from first + * write to last read, but currently the whole loop is used. + */ +TEST_F(LifetimeEvaluatorAtLeastTest, LoopWithReadWriteInSwitchSameCase) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_SWITCH, {}, {in0}, {}}, + { TGSI_OPCODE_CASE, {}, {in0}, {} }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_DEFAULT }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BRK }, + { TGSI_OPCODE_ENDSWITCH }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {3,9}})); +} + +/* First read before first write with nested loops */ +TEST_F(LifetimeEvaluatorExactTest, LoopsWithDifferentScopesCondReadBeforeWrite) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,9}})); +} + +/* First read before first write wiredness with nested loops. + * Here the first read of 2 is logically before the first, dominant + * write, therfore, the 2 has to survive both loops. + */ +TEST_F(LifetimeEvaluatorExactTest, FirstWriteAtferReadInNestedLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_MUL, {2}, {2,1}, {}}, + { TGSI_OPCODE_MOV, {3}, {2}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_ADD, {1}, {1,in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {3}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,7}, {1,7}, {4,8}})); +} + + +#define DST(X, W) vector<pair<int,int>>(1, make_pair(X, W)) +#define SRC(X, S) vector<pair<int, const char *>>(1, make_pair(X, S)) +#define SRC2(X, S, Y, T) vector<pair<int, const char *>>({make_pair(X, S), make_pair(Y, T)}) + +/* Partial write to components: one component was written unconditionally + * but another conditionally, temporary must survive the whole loop. + * Test series for all components. + */ +TEST_F(LifetimeEvaluatorExactTest, LoopWithConditionalComponentWrite_X) +{ + const vector<MockCodelineWithSwizzle> code = { + MockCodelineWithSwizzle(TGSI_OPCODE_BGNLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_Y), SRC(in1, "x"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_IF, {}, SRC(in0, "xxxx"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_X), SRC(in1, "y"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDIF), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(2, WRITEMASK_XY), SRC(1, "xy"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(out0, WRITEMASK_XYZW), SRC(2, "xyxy"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_END) + }; + run (code, expectation({{-1,-1}, {0,6}, {5,7}})); +} + +TEST_F(LifetimeEvaluatorExactTest, LoopWithConditionalComponentWrite_Y) +{ + const vector<MockCodelineWithSwizzle> code = { + MockCodelineWithSwizzle(TGSI_OPCODE_BGNLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_X), SRC(in1, "x"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_IF, {}, SRC(in0, "xxxx"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_Y), SRC(in1, "y"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDIF), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(2, WRITEMASK_XY), SRC(1, "xy"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(out0, WRITEMASK_XYZW), SRC(2, "xyxy"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_END) + }; + run (code, expectation({{-1,-1}, {0,6}, {5,7}})); +} + +TEST_F(LifetimeEvaluatorExactTest, LoopWithConditionalComponentWrite_Z) +{ + const vector<MockCodelineWithSwizzle> code = { + MockCodelineWithSwizzle(TGSI_OPCODE_BGNLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_X), SRC(in1, "x"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_IF, {}, SRC(in0, "xxxx"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_Z), SRC(in1, "y"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDIF), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(2, WRITEMASK_XY), SRC(1, "xz"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(out0, WRITEMASK_XYZW), SRC(2, "xyxy"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_END) + }; + run (code, expectation({{-1,-1}, {0,6}, {5,7}})); +} + +TEST_F(LifetimeEvaluatorExactTest, LoopWithConditionalComponentWrite_W) +{ + const vector<MockCodelineWithSwizzle> code = { + MockCodelineWithSwizzle(TGSI_OPCODE_BGNLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_X), SRC(in1, "x"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_IF, {}, SRC(in0, "xxxx"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_W), SRC(in1, "y"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDIF), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(2, WRITEMASK_XY), SRC(1, "xw"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(out0, WRITEMASK_XYZW), SRC(2, "xyxy"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_END) + }; + run (code, expectation({{-1,-1}, {0,6}, {5,7}})); +} + +TEST_F(LifetimeEvaluatorExactTest, LoopWithConditionalComponentWrite_X_Read_Y_Before) +{ + const vector<MockCodelineWithSwizzle> code = { + MockCodelineWithSwizzle(TGSI_OPCODE_BGNLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_X), SRC(in1, "x"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_IF, {}, SRC(in0, "xxxx"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(2, WRITEMASK_XYZW), SRC(1, "yyyy"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDIF), + MockCodelineWithSwizzle(TGSI_OPCODE_MOV, DST(1, WRITEMASK_YZW), SRC(2, "yyzw"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_ENDLOOP), + MockCodelineWithSwizzle(TGSI_OPCODE_ADD, DST(out0, WRITEMASK_XYZW), SRC2(2, "yyzw", 1, "xyxy"), {}), + MockCodelineWithSwizzle(TGSI_OPCODE_END) + }; + run (code, expectation({{-1,-1}, {0,7}, {0,7}})); +} + +/* The variable is conditionally read before first written, so + * it has to surive all the loops. + */ +TEST_F(LifetimeEvaluatorExactTest, FRaWSameInstructionInLoopAndCondition) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {0}, {in0}, {} }, + { TGSI_OPCODE_ADD, {1}, {1,in0}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {1}, {in1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END}, + + }; + run (code, expectation({{-1,-1}, {0,7}})); +} + +/* If unconditionally first written and read in the same + * instruction, then the register must be kept for the + * one write, but not more (undefined behaviour) + */ +TEST_F(LifetimeEvaluatorExactTest, FRaWSameInstruction) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_ADD, {1}, {1,in0}, {}}, + { TGSI_OPCODE_END}, + + }; + run (code, expectation({{-1,-1}, {0,1}})); +} + +/* If unconditionally written and read in the same + * instruction, various times then the register must be + * kept past the last write, but not longer (undefined behaviour) + */ +TEST_F(LifetimeEvaluatorExactTest, FRaWSameInstructionMoreThenOnce) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_ADD, {1}, {1,in0}, {}}, + { TGSI_OPCODE_ADD, {1}, {1,in0}, {}}, + { TGSI_OPCODE_MOV, {out0}, {in0}, {}}, + { TGSI_OPCODE_END}, + + }; + run (code, expectation({{-1,-1}, {0,2}})); +} + +/* Register is only written. This should not happen, + * but to handle the case we want the register to life + * at least one instruction + */ +TEST_F(LifetimeEvaluatorExactTest, WriteOnly) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,1}})); +} + +/* Register is read in IF. + */ +TEST_F(LifetimeEvaluatorExactTest, SimpleReadForIf) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ADD, {out0}, {in0,in1}, {}}, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_ENDIF} + }; + run (code, expectation({{-1,-1}, {0,2}})); +} + +TEST_F(LifetimeEvaluatorExactTest, WriteTwoReadOne) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_DFRACEXP , {1,2}, {in0}, {}}, + { TGSI_OPCODE_ADD , {3}, {2,in0}, {}}, + { TGSI_OPCODE_MOV, {out1}, {3}, {}}, + { TGSI_OPCODE_END}, + }; + run (code, expectation({{-1,-1}, {0,1}, {0,1}, {1,2}})); +} + +TEST_F(LifetimeEvaluatorExactTest, ReadOnly) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_END}, + }; + run (code, expectation({{-1,-1}, {-1,-1}})); +} + + +/* Test handling of missing END marker +*/ +TEST_F(LifetimeEvaluatorExactTest, SomeScopesAndNoEndProgramId) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_MOV, {2}, {1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_IF, {}, {1}, {}}, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_ENDIF}, + }; + run (code, expectation({{-1,-1}, {0,4}, {2,5}})); +} + +TEST_F(LifetimeEvaluatorExactTest, SerialReadWrite) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {2}, {1}, {}}, + { TGSI_OPCODE_MOV, {3}, {2}, {}}, + { TGSI_OPCODE_MOV, {out0}, {3}, {}}, + { TGSI_OPCODE_END}, + }; + run (code, expectation({{-1,-1}, {0,1}, {1,2}, {2,3}})); +} + +/* Check that two destination registers are used */ +TEST_F(LifetimeEvaluatorExactTest, TwoDestRegisters) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_DFRACEXP , {1,2}, {in0}, {}}, + { TGSI_OPCODE_ADD, {out0}, {1,2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,1}, {0,1}})); +} + +/* Check that writing within a loop in a conditional is propagated + * to the outer loop. + */ +TEST_F(LifetimeEvaluatorExactTest, WriteInLoopInConditionalReadOutside) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP}, + { TGSI_OPCODE_MOV, {1}, {in1}, {}}, + { TGSI_OPCODE_ENDLOOP}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ADD, {2}, {1,in1}, {}}, + { TGSI_OPCODE_ENDLOOP}, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,7}, {6,8}})); +} + +/* Check that a register written in a loop that is inside a conditional + * is not propagated past that loop if last read is also within the + * conditional +*/ +TEST_F(LifetimeEvaluatorExactTest, WriteInLoopInCondReadInCondOutsideLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP}, + { TGSI_OPCODE_MUL, {1}, {in2,in1}, {}}, + { TGSI_OPCODE_ENDLOOP}, + { TGSI_OPCODE_ADD, {2}, {1,in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDLOOP}, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {3,5}, {0,8}})); +} + +/* Check that a register read before written in a loop that is + * inside a conditional is propagated to the outer loop. + */ +TEST_F(LifetimeEvaluatorExactTest, ReadWriteInLoopInCondReadInCondOutsideLoop) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP}, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BGNLOOP}, + { TGSI_OPCODE_MUL, {1}, {1,in1}, {}}, + { TGSI_OPCODE_ENDLOOP}, + { TGSI_OPCODE_ADD, {2}, {1,in1}, {}}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_ENDLOOP}, + { TGSI_OPCODE_MOV, {out0}, {2}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,7}, {0,8}})); +} + +/* With two destinations if one value is thrown away, we must + * ensure that the two output registers don't merge. In this test + * case the last access for 2 and 3 is in line 4, but 4 can only + * be merged with 3 because it is read,2 on the other hand is written + * to, and merging it with 4 would result in a bug. + */ +TEST_F(LifetimeEvaluatorExactTest, WritePastLastRead2) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {2}, {in0}, {}}, + { TGSI_OPCODE_ADD, {3}, {1,2}, {}}, + { TGSI_OPCODE_DFRACEXP , {2,4}, {3}, {}}, + { TGSI_OPCODE_MOV, {out1}, {4}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,2}, {1,4}, {2,3}, {3,4}})); +} + +/* Check that three source registers are used */ +TEST_F(LifetimeEvaluatorExactTest, ThreeSourceRegisters) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_DFRACEXP , {1,2}, {in0}, {}}, + { TGSI_OPCODE_ADD , {3}, {in0,in1}, {}}, + { TGSI_OPCODE_MAD, {out0}, {1,2,3}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,2}, {0,2}, {1,2}})); +} + +/* Check minimal lifetime for registers only written to */ +TEST_F(LifetimeEvaluatorExactTest, OverwriteWrittenOnlyTemps) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV , {1}, {in0}, {}}, + { TGSI_OPCODE_MOV , {2}, {in1}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,1}, {1,2}})); +} + +/* Same register is only written twice. This should not happen, + * but to handle the case we want the register to life + * at least past the last write instruction + */ +TEST_F(LifetimeEvaluatorExactTest, WriteOnlyTwiceSame) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,2}})); +} + +/* Dead code elimination should catch and remove the case + * when a variable is written after its last read, but + * we want the code to be aware of this case. + * The life time of this uselessly written variable is set + * to the instruction after the write, because + * otherwise it could be re-used too early. + */ +TEST_F(LifetimeEvaluatorExactTest, WritePastLastRead) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_MOV, {2}, {1}, {}}, + { TGSI_OPCODE_MOV, {1}, {2}, {}}, + { TGSI_OPCODE_END}, + + }; + run (code, expectation({{-1,-1}, {0,3}, {1,2}})); +} + +/* If a break is in the loop, all variables written after the + * break and used outside the loop the variable must survive the + * outer loop + */ +TEST_F(LifetimeEvaluatorExactTest, NestedLoopWithWriteAfterBreak) +{ + const vector<MockCodeline> code = { + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_BGNLOOP }, + { TGSI_OPCODE_IF, {}, {in0}, {}}, + { TGSI_OPCODE_BRK}, + { TGSI_OPCODE_ENDIF}, + { TGSI_OPCODE_MOV, {1}, {in0}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_MOV, {out0}, {1}, {}}, + { TGSI_OPCODE_ENDLOOP }, + { TGSI_OPCODE_END} + }; + run (code, expectation({{-1,-1}, {0,8}})); +} + +/* Test remapping table of registers. The tests don't assume + * that the sorting algorithm used to sort the lifetimes + * based on their 'begin' is stable. + */ +TEST_F(RegisterRemappingTest, RegisterRemapping1) +{ + vector<lifetime> lt({{-1,-1}, + {0,1}, + {0,2}, + {1,2}, + {2,10}, + {3,5}, + {5,10} + }); + + vector<int> expect({0,1,2,1,1,2,2}); + run(lt, expect); +} + +TEST_F(RegisterRemappingTest, RegisterRemapping2) +{ + vector<lifetime> lt({{-1,-1}, + {0,1}, + {0,2}, + {3,4}, + {4,5}, + }); + vector<int> expect({0,1,2,1,1}); + run(lt, expect); +} + +TEST_F(RegisterRemappingTest, RegisterRemappingMergeAllToOne) +{ + vector<lifetime> lt({{-1,-1}, + {0,1}, + {1,2}, + {2,3}, + {3,4}, + }); + vector<int> expect({0,1,1,1,1}); + run(lt, expect); +} + +TEST_F(RegisterRemappingTest, RegisterRemappingIgnoreUnused) +{ + vector<lifetime> lt({{-1,-1}, + {0,1}, + {1,2}, + {2,3}, + {-1,-1}, + {3,4}, + }); + vector<int> expect({0,1,1,1,4,1}); + run(lt, expect); +} + +TEST_F(RegisterRemappingTest, RegisterRemappingMergeZeroLifetimeRegisters) +{ + vector<lifetime> lt({{-1,-1}, + {0,1}, + {1,2}, + {2,3}, + {3,3}, + {3,4}, + }); + vector<int> expect({0,1,1,1,1,1}); + run(lt, expect); +} + +TEST_F(RegisterLifetimeAndRemappingTest, LifetimeAndRemapping) +{ + const vector<MockCodeline> code = { + {TGSI_OPCODE_USEQ, {5}, {in0,in1}, {}}, + {TGSI_OPCODE_UCMP, {1}, {5,in1,1}, {}}, + {TGSI_OPCODE_UCMP, {1}, {5,in1,1}, {}}, + {TGSI_OPCODE_UCMP, {1}, {5,in1,1}, {}}, + {TGSI_OPCODE_UCMP, {1}, {5,in1,1}, {}}, + {TGSI_OPCODE_FSLT, {2}, {1,in1}, {}}, + {TGSI_OPCODE_UIF, {}, {2}, {}}, + { TGSI_OPCODE_MOV, {3}, {in1}, {}}, + {TGSI_OPCODE_ELSE}, + { TGSI_OPCODE_MOV, {4}, {in1}, {}}, + { TGSI_OPCODE_MOV, {4}, {4}, {}}, + { TGSI_OPCODE_MOV, {3}, {4}, {}}, + {TGSI_OPCODE_ENDIF}, + {TGSI_OPCODE_MOV, {out1}, {3}, {}}, + {TGSI_OPCODE_END} + }; + run (code, vector<int>({0,1,5,5,1,5})); +} + +TEST_F(RegisterLifetimeAndRemappingTest, LifetimeAndRemappingWithUnusedReadOnlyIgnored) +{ + const vector<MockCodeline> code = { + {TGSI_OPCODE_USEQ, {1}, {in0,in1}, {}}, + {TGSI_OPCODE_UCMP, {2}, {1,in1,2}, {}}, + {TGSI_OPCODE_UCMP, {4}, {2,in1,1}, {}}, + {TGSI_OPCODE_ADD, {5}, {2,4}, {}}, + {TGSI_OPCODE_UIF, {}, {7}, {}}, + { TGSI_OPCODE_ADD, {8}, {5,4}, {}}, + {TGSI_OPCODE_ENDIF}, + {TGSI_OPCODE_MOV, {out1}, {8}, {}}, + {TGSI_OPCODE_END} + }; + /* lt: 1: 0-2,2: 1-3 3: u 4: 2-5 5: 3-5 6: u 7: 0-(-1),8: 5-7 */ + run (code, vector<int>({0,1,2,3,1,2,6,7,1})); +} + +TEST_F(RegisterLifetimeAndRemappingTest, LifetimeAndRemappingWithUnusedReadOnlyRemappedTo) +{ + const vector<MockCodeline> code = { + {TGSI_OPCODE_USEQ, {1}, {in0,in1}, {}}, + {TGSI_OPCODE_UIF, {}, {7}, {}}, + { TGSI_OPCODE_UCMP, {2}, {1,in1,2}, {}}, + { TGSI_OPCODE_UCMP, {4}, {2,in1,1}, {}}, + { TGSI_OPCODE_ADD, {5}, {2,4}, {}}, + { TGSI_OPCODE_ADD, {8}, {5,4}, {}}, + {TGSI_OPCODE_ENDIF}, + {TGSI_OPCODE_MOV, {out1}, {8}, {}}, + {TGSI_OPCODE_END} + }; + /* lt: 1: 0-3,2: 2-4 3: u 4: 3-5 5: 4-5 6: u 7: 1-1,8: 5-7 */ + run (code, vector<int>({0,1,2,3,1,2,6,7,1})); +} + +TEST_F(RegisterLifetimeAndRemappingTest, LifetimeAndRemappingWithUnusedReadOnlyRemapped) +{ + const vector<MockCodeline> code = { + {TGSI_OPCODE_USEQ, {0}, {in0,in1}, {}}, + {TGSI_OPCODE_UCMP, {2}, {0,in1,2}, {}}, + {TGSI_OPCODE_UCMP, {4}, {2,in1,0}, {}}, + {TGSI_OPCODE_UIF, {}, {7}, {}}, + { TGSI_OPCODE_ADD, {5}, {4,4}, {}}, + { TGSI_OPCODE_ADD, {8}, {5,4}, {}}, + {TGSI_OPCODE_ENDIF}, + {TGSI_OPCODE_MOV, {out1}, {8}, {}}, + {TGSI_OPCODE_END} + }; + /* lt: 0: 0-2 1: u 2: 1-2 3: u 4: 2-5 5: 4-5 6: u 7:ro 8: 5-7 */ + run (code, vector<int>({0,1,2,3,0,2,6,7,0})); +} + +/* Implementation of helper and test classes */ +MockShader::~MockShader() +{ + free(); + ralloc_free(mem_ctx); +} + +MockShader::MockShader(const vector<MockCodelineWithSwizzle>& source): + num_temps(0) +{ + mem_ctx = ralloc_context(NULL); + + program = new(mem_ctx) exec_list(); + + for (MockCodelineWithSwizzle i: source) { + glsl_to_tgsi_instruction *next_instr = new(mem_ctx) glsl_to_tgsi_instruction(); + next_instr->op = i.op; + next_instr->info = tgsi_get_opcode_info(i.op); + + assert(i.src.size() < 4); + assert(i.dst.size() < 3); + assert(i.tex_offsets.size() < 3); + + for (unsigned k = 0; k < i.src.size(); ++k) { + next_instr->src[k] = create_src_register(i.src[k].first, i.src[k].second); + } + for (unsigned k = 0; k < i.dst.size(); ++k) { + next_instr->dst[k] = create_dst_register(i.dst[k].first, i.dst[k].second); + } + next_instr->tex_offset_num_offset = i.tex_offsets.size(); + next_instr->tex_offsets = new st_src_reg[i.tex_offsets.size()]; + for (unsigned k = 0; k < i.tex_offsets.size(); ++k) { + next_instr->tex_offsets[k] = create_src_register(i.tex_offsets[k].first, + i.tex_offsets[k].second); + } + program->push_tail(next_instr); + } + ++num_temps; +} + +MockShader::MockShader(const vector<MockCodeline>& source): + num_temps(0) +{ + mem_ctx = ralloc_context(NULL); + + program = new(mem_ctx) exec_list(); + + for (MockCodeline i: source) { + glsl_to_tgsi_instruction *next_instr = new(mem_ctx) glsl_to_tgsi_instruction(); + next_instr->op = i.op; + next_instr->info = tgsi_get_opcode_info(i.op); + + assert(i.src.size() < 4); + assert(i.dst.size() < 3); + assert(i.tex_offsets.size() < 3); + + for (unsigned k = 0; k < i.src.size(); ++k) { + next_instr->src[k] = create_src_register(i.src[k]); + } + for (unsigned k = 0; k < i.dst.size(); ++k) { + next_instr->dst[k] = create_dst_register(i.dst[k]); + } + next_instr->tex_offset_num_offset = i.tex_offsets.size(); + next_instr->tex_offsets = new st_src_reg[i.tex_offsets.size()]; + for (unsigned k = 0; k < i.tex_offsets.size(); ++k) { + next_instr->tex_offsets[k] = create_src_register(i.tex_offsets[k]); + } + program->push_tail(next_instr); + } + ++num_temps; +} + +int MockShader::get_num_temps() const +{ + return num_temps; +} + + +exec_list* MockShader::get_program() const +{ + return program; +} + +void MockShader::free() +{ + /* The list is not fully initialized, so + * tearing it down also must be done manually. */ + exec_node *p; + while ((p = program->pop_head())) { + glsl_to_tgsi_instruction * instr = static_cast<glsl_to_tgsi_instruction *>(p); + if (instr->tex_offset_num_offset > 0) + delete[] instr->tex_offsets; + delete p; + } + program = 0; + num_temps = 0; +} + +st_src_reg MockShader::create_src_register(int src_idx) +{ + gl_register_file file; + int idx = 0; + if (src_idx >= 0) { + file = PROGRAM_TEMPORARY; + idx = src_idx; + if (num_temps < idx) + num_temps = idx; + } else { + file = PROGRAM_INPUT; + idx = 1 - src_idx; + } + return st_src_reg(file, idx, GLSL_TYPE_INT); +} + +st_src_reg MockShader::create_src_register(int src_idx, const char *sw) +{ + uint16_t swizzle = 0; + for (int i = 0; i < 4; ++i) { + switch (sw[i]) { + case 'x': break; /* is zero */ + case 'y': swizzle |= SWIZZLE_Y << 3 * i; break; + case 'z': swizzle |= SWIZZLE_Z << 3 * i; break; + case 'w': swizzle |= SWIZZLE_W << 3 * i; break; + } + } + + gl_register_file file; + int idx = 0; + if (src_idx >= 0) { + file = PROGRAM_TEMPORARY; + idx = src_idx; + if (num_temps < idx) + num_temps = idx; + } else { + file = PROGRAM_INPUT; + idx = 1 - src_idx; + } + st_src_reg result(file, idx, GLSL_TYPE_INT); + result.swizzle = swizzle; + return result; +} + +st_dst_reg MockShader::create_dst_register(int dst_idx,int writemask) +{ + gl_register_file file; + int idx = 0; + if (dst_idx >= 0) { + file = PROGRAM_TEMPORARY; + idx = dst_idx; + if (num_temps < idx) + num_temps = idx; + } else { + file = PROGRAM_OUTPUT; + idx = 1 - dst_idx; + } + return st_dst_reg(file, writemask, GLSL_TYPE_INT, idx); +} + +st_dst_reg MockShader::create_dst_register(int dst_idx) +{ + gl_register_file file; + int idx = 0; + if (dst_idx >= 0) { + file = PROGRAM_TEMPORARY; + idx = dst_idx; + if (num_temps < idx) + num_temps = idx; + } else { + file = PROGRAM_OUTPUT; + idx = 1 - dst_idx; + } + return st_dst_reg(file,0xF, GLSL_TYPE_INT, idx); +} + + +void MesaTestWithMemCtx::SetUp() +{ + mem_ctx = ralloc_context(nullptr); +} + +void MesaTestWithMemCtx::TearDown() +{ + ralloc_free(mem_ctx); + mem_ctx = nullptr; +} + +void LifetimeEvaluatorTest::run(const vector<MockCodeline>& code, const expectation& e) +{ + MockShader shader(code); + std::vector<lifetime> result(shader.get_num_temps()); + + bool success = + get_temp_registers_required_lifetimes(mem_ctx, shader.get_program(), + shader.get_num_temps(), &result[0]); + + ASSERT_TRUE(success); + ASSERT_EQ(result.size(), e.size()); + check(result, e); +} + +void LifetimeEvaluatorTest::run(const vector<MockCodelineWithSwizzle>& code, + const expectation& e) +{ + MockShader shader(code); + std::vector<lifetime> result(shader.get_num_temps()); + + bool success = + get_temp_registers_required_lifetimes(mem_ctx, shader.get_program(), + shader.get_num_temps(), &result[0]); + ASSERT_TRUE(success); + ASSERT_EQ(result.size(), e.size()); + check(result, e); +} + +void LifetimeEvaluatorExactTest::check( const vector<lifetime>& lifetimes, + const expectation& e) +{ + for (unsigned i = 1; i < lifetimes.size(); ++i) { + EXPECT_EQ(lifetimes[i].begin, e[i][0]); + EXPECT_EQ(lifetimes[i].end, e[i][1]); + } +} + +void LifetimeEvaluatorAtLeastTest::check( const vector<lifetime>& lifetimes, + const expectation& e) +{ + for (unsigned i = 1; i < lifetimes.size(); ++i) { + EXPECT_LE(lifetimes[i].begin, e[i][0]); + EXPECT_GE(lifetimes[i].end, e[i][1]); + } +} + +void RegisterRemappingTest::run(const vector<lifetime>& lt, + const vector<int>& expect) +{ + rename_reg_pair proto{false,0}; + vector<rename_reg_pair> result(lt.size(), proto); + + get_temp_registers_remapping(mem_ctx, lt.size(), <[0], &result[0]); + + vector<int> remap(lt.size()); + for (unsigned i = 0; i < lt.size(); ++i) { + remap[i] = result[i].valid ? result[i].new_reg : i; + } + + std::transform(remap.begin(), remap.end(), result.begin(), remap.begin(), + [](int x, const rename_reg_pair& rn) { + return rn.valid ? rn.new_reg : x; + }); + + for(unsigned i = 1; i < remap.size(); ++i) { + EXPECT_EQ(remap[i], expect[i]); + } +} diff --git a/lib/mesa/src/mesa/tnl/t_vertex.c b/lib/mesa/src/mesa/tnl/t_vertex.c index c3294b007..76ff97720 100644 --- a/lib/mesa/src/mesa/tnl/t_vertex.c +++ b/lib/mesa/src/mesa/tnl/t_vertex.c @@ -28,6 +28,7 @@ #include <stdio.h> #include "main/glheader.h" #include "main/context.h" +#include "main/execmem.h" #include "swrast/s_chan.h" #include "t_context.h" #include "t_vertex.h" diff --git a/lib/mesa/src/mesa/x86/rtasm/x86sse.c b/lib/mesa/src/mesa/x86/rtasm/x86sse.c index c9f52a44d..ddb2ec373 100644 --- a/lib/mesa/src/mesa/x86/rtasm/x86sse.c +++ b/lib/mesa/src/mesa/x86/rtasm/x86sse.c @@ -4,6 +4,7 @@ #include <stdio.h> #include "main/imports.h" +#include "main/execmem.h" #include "x86sse.h" #define DISASSEM 0 diff --git a/lib/mesa/src/util/debug.h b/lib/mesa/src/util/debug.h index 11a8561eb..75ebc2ebf 100644 --- a/lib/mesa/src/util/debug.h +++ b/lib/mesa/src/util/debug.h @@ -21,8 +21,8 @@ * IN THE SOFTWARE. */ -#ifndef _DEBUG_H -#define _DEBUG_H +#ifndef _UTIL_DEBUG_H +#define _UTIL_DEBUG_H #include <stdint.h> #include <stdbool.h> @@ -46,4 +46,4 @@ env_var_as_boolean(const char *var_name, bool default_value); } /* extern C */ #endif -#endif /* _DEBUG_H */ +#endif /* _UTIL_DEBUG_H */ diff --git a/lib/mesa/src/util/drirc b/lib/mesa/src/util/drirc new file mode 100644 index 000000000..6ed35d8f4 --- /dev/null +++ b/lib/mesa/src/util/drirc @@ -0,0 +1,286 @@ +<!-- + +============================================ +Application bugs worked around in this file: +============================================ + +* Unigine Heaven 3.0 and older contain too many bugs and can't be supported + by drivers that want to be compliant. + +* Various Unigine products don't use the #version and #extension GLSL + directives, meaning they only get GLSL 1.10 and no extensions for their + shaders. + Enabling all extensions for Unigine fixes most issues, but the GLSL version + is still 1.10. + +* If ARB_sample_shading is supported, Unigine Heaven 4.0 and Valley 1.0 uses + an #extension directive in the middle of its shaders, which is illegal + in GLSL. + +* Dying Light and Dead Island Definitive Edition redeclare vertex shader + built-ins (specifically gl_VertexID), which causes the vertex shaders to fail + to compile. + +TODO: document the other workarounds. + +--> + +<driconf> + <!-- Please always enable app-specific workarounds for all drivers and + screens. --> + <device> + <application name="Unigine Sanctuary" executable="Sanctuary"> + <option name="force_glsl_extensions_warn" value="true" /> + <option name="disable_blend_func_extended" value="true" /> + </application> + + <application name="Unigine Tropics" executable="Tropics"> + <option name="force_glsl_extensions_warn" value="true" /> + <option name="disable_blend_func_extended" value="true" /> + </application> + + <application name="Unigine Heaven (32-bit)" executable="heaven_x86"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + <!-- remove dual_color_blend_by_location if 4.1 ever comes out --> + <option name="dual_color_blend_by_location" value="true" /> + </application> + + <application name="Unigine Heaven (64-bit)" executable="heaven_x64"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + <!-- remove dual_color_blend_by_location if 4.1 ever comes out --> + <option name="dual_color_blend_by_location" value="true" /> + </application> + + <application name="Unigine Valley (32-bit)" executable="valley_x86"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + <!-- remove dual_color_blend_by_location if 1.1 ever comes out --> + <option name="dual_color_blend_by_location" value="true" /> + </application> + + <application name="Unigine Valley (64-bit)" executable="valley_x64"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + <!-- remove dual_color_blend_by_location if 1.1 ever comes out --> + <option name="dual_color_blend_by_location" value="true" /> + </application> + + <application name="Unigine OilRush (32-bit)" executable="OilRush_x86"> + <option name="disable_blend_func_extended" value="true" /> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + </application> + + <application name="Unigine OilRush (64-bit)" executable="OilRush_x64"> + <option name="disable_blend_func_extended" value="true" /> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + </application> + + <application name="Savage 2" executable="savage2.bin"> + <option name="disable_glsl_line_continuations" value="true" /> + </application> + + <application name="Topogun (32-bit)" executable="topogun32"> + <option name="always_have_depth_buffer" value="true" /> + </application> + + <application name="Topogun (64-bit)" executable="topogun64"> + <option name="always_have_depth_buffer" value="true" /> + </application> + + <application name="Dead Island (incl. Definitive Edition)" executable="DeadIslandGame"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + + <!-- For the Definitive Edition which shares the same executable name --> + <option name="allow_glsl_builtin_variable_redeclaration" value="true" /> + </application> + + <application name="Dead Island Riptide Definitive Edition" executable="DeadIslandRiptideGame"> + <option name="allow_glsl_builtin_variable_redeclaration" value="true" /> + </application> + + <application name="Dying Light" executable="DyingLightGame"> + <option name="allow_glsl_builtin_variable_redeclaration" value="true" /> + </application> + + <application name="Second Life" executable="do-not-directly-run-secondlife-bin"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + </application> + + <application name="Warsow (32-bit)" executable="warsow.i386"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + </application> + + <application name="Warsow (64-bit)" executable="warsow.x86_64"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + </application> + + <application name="Rust" executable="rust"> + <option name="glsl_zero_init" value="true"/> + </application> + + <application name="Divinity: Original Sin Enhanced Edition" executable="EoCApp"> + <option name="allow_glsl_extension_directive_midshader" value="true" /> + </application> + + <application name="Worms W.M.D" executable="Worms W.M.Dx64"> + <option name="allow_higher_compat_version" value="true" /> + </application> + + <application name="Crookz - The Big Heist" executable="Crookz"> + <option name="allow_higher_compat_version" value="true" /> + </application> + + <application name="Tropico 5" executable="Tropico5"> + <option name="allow_higher_compat_version" value="true" /> + </application> + + <application name="The Culling" executable="Victory"> + <option name="force_glsl_version" value="440" /> + </application> + + <application name="Spec Ops: The Line (32-bit)" executable="specops.i386"> + <option name="force_glsl_abs_sqrt" value="true" /> + </application> + + <application name="Spec Ops: The Line (64-bit)" executable="specops"> + <option name="force_glsl_abs_sqrt" value="true" /> + </application> + + <application name="Kerbal Space Program (32-bit)" executable="KSP.x86"> + <option name="glsl_zero_init" value="true"/> + </application> + + <application name="Kerbal Space Program (64-bit)" executable="KSP.x86_64"> + <option name="glsl_zero_init" value="true"/> + </application> + + <application name="Rocket League" executable="RocketLeague"> + <option name="glsl_correct_derivatives_after_discard" value="true"/> + </application> + + <application name="The Witcher 2" executable="witcher2"> + <option name="glsl_correct_derivatives_after_discard" value="true"/> + </application> + + <application name="Unreal 4 Editor" executable="UE4Editor"> + <option name="allow_glsl_cross_stage_interpolation_mismatch" value="true"/> + </application> + + <application name="Observer" executable="TheObserver-Linux-Shipping"> + <option name="allow_glsl_cross_stage_interpolation_mismatch" value="true"/> + </application> + + <application name="Steamroll" executable="Steamroll-Linux-Shipping"> + <option name="allow_glsl_cross_stage_interpolation_mismatch" value="true"/> + </application> + + <application name="Refunct" executable="Refunct-Linux-Shipping"> + <option name="allow_glsl_cross_stage_interpolation_mismatch" value="true"/> + </application> + + <!-- The GL thread whitelist is below, workarounds are above. + Keep it that way. --> + + <application name="Alien Isolation" executable="AlienIsolation"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="BioShock Infinite" executable="bioshock.i386"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Borderlands 2" executable="Borderlands2"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Civilization 5" executable="Civ5XP"> + <option name="mesa_glthread" value="true"/> + </application> + <application name="Civilization 6" executable="Civ6"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Dreamfall Chapters" executable="Dreamfall Chapters"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Hitman" executable="HitmanPro"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Renowned Explorers: International Society" executable="abbeycore_steam"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Saints Row 2" executable="saintsrow2.i386"> + <option name="mesa_glthread" value="true"/> + </application> + <application name="Saints Row: The Third" executable="SaintsRow3.i386"> + <option name="mesa_glthread" value="true"/> + </application> + <application name="Saints Row IV" executable="SaintsRow4.i386"> + <option name="mesa_glthread" value="true"/> + </application> + <application name="Saints Row: Gat out of Hell" executable="SaintsRow4GooH.i386"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Sid Meier's: Civilization Beyond Earth" executable="CivBE"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="The Witcher 2" executable="witcher2"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="American Truck Simulator" executable="amtrucks"> + <option name="mesa_glthread" value="true"/> + </application> + <application name="Euro Truck Simulator 2" executable="eurotrucks2"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Overlord" executable="overlord.i386"> + <option name="mesa_glthread" value="true"/> + </application> + <application name="Overlord 2" executable="overlord2.i386"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Oil Rush" executable="OilRush_x86"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="War Thunder" executable="aces"> + <option name="mesa_glthread" value="true"/> + </application> + <application name="War Thunder (Wine)" executable="aces.exe"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Outlast" executable="OLGame.x86_64"> + <option name="mesa_glthread" value="true"/> + </application> + + <application name="Spec Ops: The Line (32-bit)" executable="specops.i386"> + <option name="mesa_glthread" value="true"/> + </application> + <application name="Spec Ops: The Line (64-bit)" executable="specops"> + <option name="mesa_glthread" value="true"/> + </application> + </device> + <!-- vmwgfx doesn't like full buffer swaps and can't sync to vertical retraces.--> + <device driver="vmwgfx"> + <application name="gnome-shell" executable="gnome-shell"> + <option name="glx_disable_ext_buffer_age" value="true" /> + <option name="glx_disable_oml_sync_control" value="true" /> + </application> + <application name="Compiz" executable="Compiz"> + <option name="glx_disable_ext_buffer_age" value="true" /> + <option name="glx_disable_oml_sync_control" value="true" /> + </application> + </device> + <device driver="radeonsi"> + <application name="ARK: Survival Evolved (and unintentionally the UE4 demo template)" executable="ShooterGame"> + <option name="radeonsi_clear_db_cache_before_clear" value="true" /> + </application> + </device> +</driconf> diff --git a/lib/mesa/src/util/half_float.h b/lib/mesa/src/util/half_float.h index 64f204210..b3bc3f687 100644 --- a/lib/mesa/src/util/half_float.h +++ b/lib/mesa/src/util/half_float.h @@ -25,6 +25,7 @@ #ifndef _HALF_FLOAT_H_ #define _HALF_FLOAT_H_ +#include <stdbool.h> #include <stdint.h> #ifdef __cplusplus @@ -34,6 +35,13 @@ extern "C" { uint16_t _mesa_float_to_half(float val); float _mesa_half_to_float(uint16_t val); +static inline bool +_mesa_half_is_negative(uint16_t h) +{ + return !!(h & 0x8000); +} + + #ifdef __cplusplus } /* extern C */ #endif diff --git a/lib/mesa/src/util/merge_driinfo.py b/lib/mesa/src/util/merge_driinfo.py new file mode 100644 index 000000000..e6ccca5e0 --- /dev/null +++ b/lib/mesa/src/util/merge_driinfo.py @@ -0,0 +1,222 @@ +# +# Copyright 2017 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# 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. + +""" +usage: merge_driinfo.py <list of input files> + +Generates a source file which contains the DRI_CONF_xxx macros for generating +the driinfo XML that describes the available DriConf options for a driver and +its supported state trackers, based on the merged information from the input +files. +""" + +from __future__ import print_function + +import mako.template +import re +import sys + + +# Some regexps used during input parsing +RE_section_begin = re.compile(r'DRI_CONF_SECTION_(.*)') +RE_option = re.compile(r'DRI_CONF_(.*)\((.*)\)') + + +class Option(object): + """ + Represent a config option as: + * name: the xxx part of the DRI_CONF_xxx macro + * defaults: the defaults parameters that are passed into the macro + """ + def __init__(self, name, defaults): + self.name = name + self.defaults = defaults + + +class Section(object): + """ + Represent a config section description as: + * name: the xxx part of the DRI_CONF_SECTION_xxx macro + * options: list of options + """ + def __init__(self, name): + self.name = name + self.options = [] + + +def parse_inputs(input_filenames): + success = True + sections_lists = [] + + for input_filename in input_filenames: + with open(input_filename, 'r') as infile: + sections = [] + sections_lists.append(sections) + + section = None + + linenum = 0 + for line in infile: + linenum += 1 + line = line.strip() + if not line: + continue + + if line.startswith('//'): + continue + + if line == 'DRI_CONF_SECTION_END': + if section is None: + print('{}:{}: no open section' + .format(input_filename, linenum)) + success = False + continue + section = None + continue + + m = RE_section_begin.match(line) + if m: + if section is not None: + print('{}:{}: nested sections are not supported' + .format(input_filename, linenum)) + success = False + continue + if sections is None: + print('{}:{}: missing DRIINFO line' + .format(input_filename, linenum)) + success = False + break # parsing the rest really makes no sense + section = Section(m.group(1)) + sections.append(section) + continue + + m = RE_option.match(line) + if m: + if section is None: + print('{}:{}: no open section' + .format(input_filename, linenum)) + success = False + break + section.options.append(Option(m.group(1), m.group(2))) + continue + + print('{}:{}: do not understand this line' + .format(input_filename, linenum)) + success = False + + if section is not None: + print('{}:end-of-file: missing end of section' + .format(input_filename)) + success = False + + if success: + return sections_lists + return None + + +def merge_sections(section_list): + """ + section_list: list of Section objects to be merged, all of the same name + Return a merged Section object (everything is deeply copied) + """ + merged_section = Section(section_list[0].name) + + for section in section_list: + assert section.name == merged_section.name + + for orig_option in section.options: + for merged_option in merged_section.options: + if orig_option.name == merged_option.name: + merged_option.defaults = orig_option.defaults + break + else: + merged_section.options.append(Option(orig_option.name, orig_option.defaults)) + + return merged_section + + +def merge_sections_lists(sections_lists): + """ + sections_lists: list of lists of Section objects to be merged + Return a merged list of merged Section objects; everything is deeply copied. + Default values for options in later lists override earlier default values. + """ + merged_sections = [] + + for idx,sections in enumerate(sections_lists): + for base_section in sections: + original_sections = [base_section] + for next_sections in sections_lists[idx+1:]: + for j,section in enumerate(next_sections): + if section.name == base_section.name: + original_sections.append(section) + del next_sections[j] + break + + merged_section = merge_sections(original_sections) + + merged_sections.append(merged_section) + + return merged_sections + + +def main(input_filenames): + sections_lists = parse_inputs(input_filenames) + if sections_lists is None: + return False + + merged_sections_list = merge_sections_lists(sections_lists) + + driinfo_h_template = mako.template.Template("""\ +// DO NOT EDIT - this file is automatically generated by merge_driinfo.py + +/* +Use as: + +#include "xmlpool.h" + +static const char driinfo_xml[] = +#include "this_file" +; +*/ + +DRI_CONF_BEGIN +% for section in sections: + DRI_CONF_SECTION_${section.name} +% for option in section.options: + DRI_CONF_${option.name}(${option.defaults}) +% endfor + DRI_CONF_SECTION_END +% endfor +DRI_CONF_END""") + + print(driinfo_h_template.render(sections=merged_sections_list)) + return True + + +if __name__ == '__main__': + if len(sys.argv) <= 1: + print('Missing arguments') + sys.exit(1) + + if not main(sys.argv[1:]): + sys.exit(1) diff --git a/lib/mesa/src/util/register_allocate.c b/lib/mesa/src/util/register_allocate.c index 8af93c040..de8978bb9 100644 --- a/lib/mesa/src/util/register_allocate.c +++ b/lib/mesa/src/util/register_allocate.c @@ -174,6 +174,10 @@ struct ra_graph { * stack. */ unsigned int stack_optimistic_start; + + unsigned int (*select_reg_callback)(struct ra_graph *g, BITSET_WORD *regs, + void *data); + void *select_reg_callback_data; }; /** @@ -392,11 +396,11 @@ ra_add_node_adjacency(struct ra_graph *g, unsigned int n1, unsigned int n2) { BITSET_SET(g->nodes[n1].adjacency, n2); - if (n1 != n2) { - int n1_class = g->nodes[n1].class; - int n2_class = g->nodes[n2].class; - g->nodes[n1].q_total += g->regs->classes[n1_class]->q[n2_class]; - } + assert(n1 != n2); + + int n1_class = g->nodes[n1].class; + int n2_class = g->nodes[n2].class; + g->nodes[n1].q_total += g->regs->classes[n1_class]->q[n2_class]; if (g->nodes[n1].adjacency_count >= g->nodes[n1].adjacency_list_size) { @@ -433,13 +437,22 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count) g->nodes[i].adjacency_count = 0; g->nodes[i].q_total = 0; - ra_add_node_adjacency(g, i, i); g->nodes[i].reg = NO_REG; } return g; } +void ra_set_select_reg_callback(struct ra_graph *g, + unsigned int (*callback)(struct ra_graph *g, + BITSET_WORD *regs, + void *data), + void *data) +{ + g->select_reg_callback = callback; + g->select_reg_callback_data = data; +} + void ra_set_node_class(struct ra_graph *g, unsigned int n, unsigned int class) @@ -451,7 +464,7 @@ void ra_add_node_interference(struct ra_graph *g, unsigned int n1, unsigned int n2) { - if (!BITSET_TEST(g->nodes[n1].adjacency, n2)) { + if (n1 != n2 && !BITSET_TEST(g->nodes[n1].adjacency, n2)) { ra_add_node_adjacency(g, n1, n2); ra_add_node_adjacency(g, n2, n1); } @@ -475,7 +488,7 @@ decrement_q(struct ra_graph *g, unsigned int n) unsigned int n2 = g->nodes[n].adjacency_list[i]; unsigned int n2_class = g->nodes[n2].class; - if (n != n2 && !g->nodes[n2].in_stack) { + if (!g->nodes[n2].in_stack) { assert(g->nodes[n2].q_total >= g->regs->classes[n2_class]->q[n_class]); g->nodes[n2].q_total -= g->regs->classes[n2_class]->q[n_class]; } @@ -539,6 +552,58 @@ ra_simplify(struct ra_graph *g) g->stack_optimistic_start = stack_optimistic_start; } +static bool +ra_any_neighbors_conflict(struct ra_graph *g, unsigned int n, unsigned int r) +{ + unsigned int i; + + for (i = 0; i < g->nodes[n].adjacency_count; i++) { + unsigned int n2 = g->nodes[n].adjacency_list[i]; + + if (!g->nodes[n2].in_stack && + BITSET_TEST(g->regs->regs[r].conflicts, g->nodes[n2].reg)) { + return true; + } + } + + return false; +} + +/* Computes a bitfield of what regs are available for a given register + * selection. + * + * This lets drivers implement a more complicated policy than our simple first + * or round robin policies (which don't require knowing the whole bitset) + */ +static bool +ra_compute_available_regs(struct ra_graph *g, unsigned int n, BITSET_WORD *regs) +{ + struct ra_class *c = g->regs->classes[g->nodes[n].class]; + + /* Populate with the set of regs that are in the node's class. */ + memcpy(regs, c->regs, BITSET_WORDS(g->regs->count) * sizeof(BITSET_WORD)); + + /* Remove any regs that conflict with nodes that we're adjacent to and have + * already colored. + */ + for (int i = 0; i < g->nodes[n].adjacency_count; i++) { + unsigned int n2 = g->nodes[n].adjacency_list[i]; + unsigned int r = g->nodes[n2].reg; + + if (!g->nodes[n2].in_stack) { + for (int j = 0; j < BITSET_WORDS(g->regs->count); j++) + regs[j] &= ~g->regs->regs[r].conflicts[j]; + } + } + + for (int i = 0; i < BITSET_WORDS(g->regs->count); i++) { + if (regs[i]) + return true; + } + + return false; +} + /** * Pops nodes from the stack back into the graph, coloring them with * registers as they go. @@ -550,42 +615,45 @@ static bool ra_select(struct ra_graph *g) { int start_search_reg = 0; + BITSET_WORD *select_regs = NULL; + + if (g->select_reg_callback) + select_regs = malloc(BITSET_WORDS(g->regs->count) * sizeof(BITSET_WORD)); while (g->stack_count != 0) { - unsigned int i; unsigned int ri; unsigned int r = -1; int n = g->stack[g->stack_count - 1]; struct ra_class *c = g->regs->classes[g->nodes[n].class]; - /* Find the lowest-numbered reg which is not used by a member - * of the graph adjacent to us. - */ - for (ri = 0; ri < g->regs->count; ri++) { - r = (start_search_reg + ri) % g->regs->count; - if (!reg_belongs_to_class(r, c)) - continue; - - /* Check if any of our neighbors conflict with this register choice. */ - for (i = 0; i < g->nodes[n].adjacency_count; i++) { - unsigned int n2 = g->nodes[n].adjacency_list[i]; - - if (!g->nodes[n2].in_stack && - BITSET_TEST(g->regs->regs[r].conflicts, g->nodes[n2].reg)) { - break; - } - } - if (i == g->nodes[n].adjacency_count) - break; - } - /* set this to false even if we return here so that * ra_get_best_spill_node() considers this node later. */ g->nodes[n].in_stack = false; - if (ri == g->regs->count) - return false; + if (g->select_reg_callback) { + if (!ra_compute_available_regs(g, n, select_regs)) { + free(select_regs); + return false; + } + + r = g->select_reg_callback(g, select_regs, g->select_reg_callback_data); + } else { + /* Find the lowest-numbered reg which is not used by a member + * of the graph adjacent to us. + */ + for (ri = 0; ri < g->regs->count; ri++) { + r = (start_search_reg + ri) % g->regs->count; + if (!reg_belongs_to_class(r, c)) + continue; + + if (!ra_any_neighbors_conflict(g, n, r)) + break; + } + + if (ri >= g->regs->count) + return false; + } g->nodes[n].reg = r; g->stack_count--; @@ -604,6 +672,8 @@ ra_select(struct ra_graph *g) start_search_reg = r + 1; } + free(select_regs); + return true; } @@ -654,11 +724,9 @@ ra_get_spill_benefit(struct ra_graph *g, unsigned int n) */ for (j = 0; j < g->nodes[n].adjacency_count; j++) { unsigned int n2 = g->nodes[n].adjacency_list[j]; - if (n != n2) { - unsigned int n2_class = g->nodes[n2].class; - benefit += ((float)g->regs->classes[n_class]->q[n2_class] / - g->regs->classes[n_class]->p); - } + unsigned int n2_class = g->nodes[n2].class; + benefit += ((float)g->regs->classes[n_class]->q[n2_class] / + g->regs->classes[n_class]->p); } return benefit; diff --git a/lib/mesa/src/util/string_buffer.c b/lib/mesa/src/util/string_buffer.c new file mode 100644 index 000000000..c33173bfa --- /dev/null +++ b/lib/mesa/src/util/string_buffer.c @@ -0,0 +1,148 @@ +/* + * Copyright © 2017 Thomas Helland + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "string_buffer.h" + +static bool +ensure_capacity(struct _mesa_string_buffer *str, uint32_t needed_capacity) +{ + if (needed_capacity <= str->capacity) + return true; + + /* Too small, double until we can fit the new string */ + uint32_t new_capacity = str->capacity * 2; + while (needed_capacity > new_capacity) + new_capacity *= 2; + + str->buf = reralloc_array_size(str, str->buf, sizeof(char), new_capacity); + if (str->buf == NULL) + return false; + + str->capacity = new_capacity; + return true; +} + +struct _mesa_string_buffer * +_mesa_string_buffer_create(void *mem_ctx, uint32_t initial_capacity) +{ + struct _mesa_string_buffer *str; + str = ralloc(mem_ctx, struct _mesa_string_buffer); + + if (str == NULL) + return NULL; + + /* If no initial capacity is set then set it to something */ + str->capacity = initial_capacity ? initial_capacity : 32; + str->buf = ralloc_array(str, char, str->capacity); + + if (!str->buf) { + ralloc_free(str); + return NULL; + } + + str->length = 0; + str->buf[str->length] = '\0'; + return str; +} + +bool +_mesa_string_buffer_append_all(struct _mesa_string_buffer *str, + uint32_t num_args, ...) +{ + int i; + char* s; + va_list args; + va_start(args, num_args); + for (i = 0; i < num_args; i++) { + s = va_arg(args, char*); + if (!_mesa_string_buffer_append_len(str, s, strlen(s))) { + va_end(args); + return false; + } + } + va_end(args); + return true; +} + +bool +_mesa_string_buffer_append_len(struct _mesa_string_buffer *str, + const char *c, uint32_t len) +{ + uint32_t needed_length = str->length + len + 1; + + /* Check if we're overflowing uint32_t */ + if (needed_length < str->length) + return false; + + if (!ensure_capacity(str, needed_length)) + return false; + + memcpy(str->buf + str->length, c, len); + str->length += len; + str->buf[str->length] = '\0'; + return true; +} + +bool +_mesa_string_buffer_vprintf(struct _mesa_string_buffer *str, + const char *format, va_list args) +{ + /* We're looping two times to avoid duplicating code */ + for (uint32_t i = 0; i < 2; i++) { + va_list arg_copy; + va_copy(arg_copy, args); + uint32_t space_left = str->capacity - str->length; + + int32_t len = util_vsnprintf(str->buf + str->length, + space_left, format, arg_copy); + va_end(arg_copy); + + /* Error in vsnprintf() or measured len overflows size_t */ + if (unlikely(len < 0 || str->length + len + 1 < str->length)) + return false; + + /* There was enough space for the string; we're done */ + if (len < space_left) { + str->length += len; + return true; + } + + /* Not enough space, resize and retry */ + ensure_capacity(str, str->length + len + 1); + } + + return false; +} + +bool +_mesa_string_buffer_printf(struct _mesa_string_buffer *str, + const char *format, ...) +{ + bool res; + va_list args; + va_start(args, format); + res = _mesa_string_buffer_vprintf(str, format, args); + va_end(args); + return res; +} diff --git a/lib/mesa/src/util/string_buffer.h b/lib/mesa/src/util/string_buffer.h new file mode 100644 index 000000000..eaaf5f33d --- /dev/null +++ b/lib/mesa/src/util/string_buffer.h @@ -0,0 +1,104 @@ +/* + * Copyright © 2017 Thomas Helland + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 _STRING_BUFFER_H +#define _STRING_BUFFER_H + +#include "ralloc.h" +#include "u_string.h" +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct _mesa_string_buffer { + char *buf; + uint32_t length; + uint32_t capacity; +}; + +struct _mesa_string_buffer * +_mesa_string_buffer_create(void *mem_ctx, uint32_t initial_capacity); + +static inline void +_mesa_string_buffer_destroy(struct _mesa_string_buffer *str) +{ + ralloc_free(str); +} + +bool +_mesa_string_buffer_append_all(struct _mesa_string_buffer *str, + uint32_t num_args, ...); +bool +_mesa_string_buffer_append_len(struct _mesa_string_buffer *str, + const char *c, uint32_t len); + +static inline bool +_mesa_string_buffer_append_char(struct _mesa_string_buffer *str, char c) +{ + return _mesa_string_buffer_append_len(str, &c, 1); +} + +static inline bool +_mesa_string_buffer_append(struct _mesa_string_buffer *str, const char *c) +{ + return _mesa_string_buffer_append_len(str, c, strlen(c)); +} + +static inline void +_mesa_string_buffer_clear(struct _mesa_string_buffer *str) +{ + str->length = 0; + str->buf[str->length] = '\0'; +} + +static inline void +_mesa_string_buffer_crimp_to_fit(struct _mesa_string_buffer *str) +{ + char *crimped = + (char *) reralloc_array_size(str, str->buf, sizeof(char), + str->capacity); + if (!crimped) + return; + + str->capacity = str->length + 1; + str->buf = crimped; +} + +bool +_mesa_string_buffer_vprintf(struct _mesa_string_buffer *str, + const char *format, va_list args); + +bool +_mesa_string_buffer_printf(struct _mesa_string_buffer *str, + const char *format, ...); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _STRING_BUFFER_H */ diff --git a/lib/mesa/src/util/tests/string_buffer/Makefile.am b/lib/mesa/src/util/tests/string_buffer/Makefile.am new file mode 100644 index 000000000..bd04d8634 --- /dev/null +++ b/lib/mesa/src/util/tests/string_buffer/Makefile.am @@ -0,0 +1,40 @@ +# Copyright © 2017 Thomas Helland +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and 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. + +AM_CPPFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gtest/include \ + $(PTHREAD_CFLAGS) \ + $(DEFINES) + +TESTS = string_buffer_test + +check_PROGRAMS = $(TESTS) + +string_buffer_test_SOURCES = \ + string_buffer_test.cpp + +string_buffer_test_LDADD = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/util/libmesautil.la \ + $(PTHREAD_LIBS) \ + $(DLOPEN_LIBS) diff --git a/lib/mesa/src/util/tests/string_buffer/Makefile.in b/lib/mesa/src/util/tests/string_buffer/Makefile.in new file mode 100644 index 000000000..a509e8305 --- /dev/null +++ b/lib/mesa/src/util/tests/string_buffer/Makefile.in @@ -0,0 +1,1188 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Copyright © 2017 Thomas Helland +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and 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. +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +TESTS = string_buffer_test$(EXEEXT) +check_PROGRAMS = $(am__EXEEXT_1) +subdir = src/util/tests/string_buffer +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_gnu_make.m4 \ + $(top_srcdir)/m4/ax_check_python_mako_module.m4 \ + $(top_srcdir)/m4/ax_gcc_builtin.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_prog_bison.m4 \ + $(top_srcdir)/m4/ax_prog_flex.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/VERSION $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__EXEEXT_1 = string_buffer_test$(EXEEXT) +am_string_buffer_test_OBJECTS = string_buffer_test.$(OBJEXT) +string_buffer_test_OBJECTS = $(am_string_buffer_test_OBJECTS) +am__DEPENDENCIES_1 = +string_buffer_test_DEPENDENCIES = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/util/libmesautil.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/bin/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(string_buffer_test_SOURCES) +DIST_SOURCES = $(string_buffer_test_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/bin/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/bin/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/bin/depcomp \ + $(top_srcdir)/bin/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDGPU_CFLAGS = @AMDGPU_CFLAGS@ +AMDGPU_LIBS = @AMDGPU_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ANDROID_CFLAGS = @ANDROID_CFLAGS@ +ANDROID_LIBS = @ANDROID_LIBS@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BSYMBOLIC = @BSYMBOLIC@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLANG_RESOURCE_DIR = @CLANG_RESOURCE_DIR@ +CLOCK_LIB = @CLOCK_LIB@ +CLOVER_STD_OVERRIDE = @CLOVER_STD_OVERRIDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +D3D_DRIVER_INSTALL_DIR = @D3D_DRIVER_INSTALL_DIR@ +DEFINES = @DEFINES@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ +DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRIGL_CFLAGS = @DRIGL_CFLAGS@ +DRIGL_LIBS = @DRIGL_LIBS@ +DRI_DRIVER_INSTALL_DIR = @DRI_DRIVER_INSTALL_DIR@ +DRI_DRIVER_SEARCH_DIR = @DRI_DRIVER_SEARCH_DIR@ +DRI_LIB_DEPS = @DRI_LIB_DEPS@ +DRI_PC_REQ_PRIV = @DRI_PC_REQ_PRIV@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGL_CFLAGS = @EGL_CFLAGS@ +EGL_LIB_DEPS = @EGL_LIB_DEPS@ +EGL_NATIVE_PLATFORM = @EGL_NATIVE_PLATFORM@ +EGREP = @EGREP@ +ETNAVIV_CFLAGS = @ETNAVIV_CFLAGS@ +ETNAVIV_LIBS = @ETNAVIV_LIBS@ +EXEEXT = @EXEEXT@ +EXPAT_CFLAGS = @EXPAT_CFLAGS@ +EXPAT_LIBS = @EXPAT_LIBS@ +FGREP = @FGREP@ +FREEDRENO_CFLAGS = @FREEDRENO_CFLAGS@ +FREEDRENO_LIBS = @FREEDRENO_LIBS@ +GALLIUM_PIPE_LOADER_DEFINES = @GALLIUM_PIPE_LOADER_DEFINES@ +GBM_PC_LIB_PRIV = @GBM_PC_LIB_PRIV@ +GBM_PC_REQ_PRIV = @GBM_PC_REQ_PRIV@ +GC_SECTIONS = @GC_SECTIONS@ +GLESv1_CM_LIB_DEPS = @GLESv1_CM_LIB_DEPS@ +GLESv1_CM_PC_LIB_PRIV = @GLESv1_CM_PC_LIB_PRIV@ +GLESv2_LIB_DEPS = @GLESv2_LIB_DEPS@ +GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@ +GLPROTO_CFLAGS = @GLPROTO_CFLAGS@ +GLPROTO_LIBS = @GLPROTO_LIBS@ +GLVND_CFLAGS = @GLVND_CFLAGS@ +GLVND_LIBS = @GLVND_LIBS@ +GLX_TLS = @GLX_TLS@ +GL_LIB = @GL_LIB@ +GL_LIB_DEPS = @GL_LIB_DEPS@ +GL_PC_CFLAGS = @GL_PC_CFLAGS@ +GL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@ +GL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@ +GREP = @GREP@ +HAVE_XF86VIDMODE = @HAVE_XF86VIDMODE@ +I915_CFLAGS = @I915_CFLAGS@ +I915_LIBS = @I915_LIBS@ +INDENT = @INDENT@ +INDENT_FLAGS = @INDENT_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LD_NO_UNDEFINED = @LD_NO_UNDEFINED@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBATOMIC_LIBS = @LIBATOMIC_LIBS@ +LIBCLC_INCLUDEDIR = @LIBCLC_INCLUDEDIR@ +LIBCLC_LIBEXECDIR = @LIBCLC_LIBEXECDIR@ +LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ +LIBDRM_LIBS = @LIBDRM_LIBS@ +LIBELF_CFLAGS = @LIBELF_CFLAGS@ +LIBELF_LIBS = @LIBELF_LIBS@ +LIBGLVND_DATADIR = @LIBGLVND_DATADIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSENSORS_LIBS = @LIBSENSORS_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIB_DIR = @LIB_DIR@ +LIB_EXT = @LIB_EXT@ +LIPO = @LIPO@ +LLVM_CFLAGS = @LLVM_CFLAGS@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_CXXFLAGS = @LLVM_CXXFLAGS@ +LLVM_INCLUDEDIR = @LLVM_INCLUDEDIR@ +LLVM_LDFLAGS = @LLVM_LDFLAGS@ +LLVM_LIBS = @LLVM_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSVC2013_COMPAT_CFLAGS = @MSVC2013_COMPAT_CFLAGS@ +MSVC2013_COMPAT_CXXFLAGS = @MSVC2013_COMPAT_CXXFLAGS@ +NINE_MAJOR = @NINE_MAJOR@ +NINE_MINOR = @NINE_MINOR@ +NINE_TINY = @NINE_TINY@ +NINE_VERSION = @NINE_VERSION@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NOUVEAU_CFLAGS = @NOUVEAU_CFLAGS@ +NOUVEAU_LIBS = @NOUVEAU_LIBS@ +NVVIEUX_CFLAGS = @NVVIEUX_CFLAGS@ +NVVIEUX_LIBS = @NVVIEUX_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OMX_BELLAGIO_CFLAGS = @OMX_BELLAGIO_CFLAGS@ +OMX_BELLAGIO_LIBS = @OMX_BELLAGIO_LIBS@ +OMX_BELLAGIO_LIB_INSTALL_DIR = @OMX_BELLAGIO_LIB_INSTALL_DIR@ +OPENCL_LIBNAME = @OPENCL_LIBNAME@ +OPENCL_VERSION = @OPENCL_VERSION@ +OSMESA_LIB = @OSMESA_LIB@ +OSMESA_LIB_DEPS = @OSMESA_LIB_DEPS@ +OSMESA_PC_LIB_PRIV = @OSMESA_PC_LIB_PRIV@ +OSMESA_PC_REQ = @OSMESA_PC_REQ@ +OSMESA_VERSION = @OSMESA_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSIX_SHELL = @POSIX_SHELL@ +PTHREADSTUBS_CFLAGS = @PTHREADSTUBS_CFLAGS@ +PTHREADSTUBS_LIBS = @PTHREADSTUBS_LIBS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PWR8_CFLAGS = @PWR8_CFLAGS@ +PYTHON2 = @PYTHON2@ +RADEON_CFLAGS = @RADEON_CFLAGS@ +RADEON_LIBS = @RADEON_LIBS@ +RANLIB = @RANLIB@ +RM = @RM@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIMPENROSE_CFLAGS = @SIMPENROSE_CFLAGS@ +SIMPENROSE_LIBS = @SIMPENROSE_LIBS@ +SSE41_CFLAGS = @SSE41_CFLAGS@ +STRIP = @STRIP@ +SWR_AVX2_CXXFLAGS = @SWR_AVX2_CXXFLAGS@ +SWR_AVX_CXXFLAGS = @SWR_AVX_CXXFLAGS@ +SWR_CXX11_CXXFLAGS = @SWR_CXX11_CXXFLAGS@ +SWR_KNL_CXXFLAGS = @SWR_KNL_CXXFLAGS@ +SWR_SKX_CXXFLAGS = @SWR_SKX_CXXFLAGS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VA_CFLAGS = @VA_CFLAGS@ +VA_LIBS = @VA_LIBS@ +VA_LIB_INSTALL_DIR = @VA_LIB_INSTALL_DIR@ +VA_MAJOR = @VA_MAJOR@ +VA_MINOR = @VA_MINOR@ +VC5_SIMULATOR_CFLAGS = @VC5_SIMULATOR_CFLAGS@ +VC5_SIMULATOR_LIBS = @VC5_SIMULATOR_LIBS@ +VDPAU_CFLAGS = @VDPAU_CFLAGS@ +VDPAU_LIBS = @VDPAU_LIBS@ +VDPAU_LIB_INSTALL_DIR = @VDPAU_LIB_INSTALL_DIR@ +VDPAU_MAJOR = @VDPAU_MAJOR@ +VDPAU_MINOR = @VDPAU_MINOR@ +VERSION = @VERSION@ +VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@ +VISIBILITY_CXXFLAGS = @VISIBILITY_CXXFLAGS@ +VL_CFLAGS = @VL_CFLAGS@ +VL_LIBS = @VL_LIBS@ +VULKAN_ICD_INSTALL_DIR = @VULKAN_ICD_INSTALL_DIR@ +WAYLAND_CLIENT_CFLAGS = @WAYLAND_CLIENT_CFLAGS@ +WAYLAND_CLIENT_LIBS = @WAYLAND_CLIENT_LIBS@ +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ +WAYLAND_SCANNER_CFLAGS = @WAYLAND_SCANNER_CFLAGS@ +WAYLAND_SCANNER_LIBS = @WAYLAND_SCANNER_LIBS@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WNO_OVERRIDE_INIT = @WNO_OVERRIDE_INIT@ +X11_INCLUDES = @X11_INCLUDES@ +XA_MAJOR = @XA_MAJOR@ +XA_MINOR = @XA_MINOR@ +XA_TINY = @XA_TINY@ +XA_VERSION = @XA_VERSION@ +XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@ +XCB_DRI2_LIBS = @XCB_DRI2_LIBS@ +XCB_DRI3_CFLAGS = @XCB_DRI3_CFLAGS@ +XCB_DRI3_LIBS = @XCB_DRI3_LIBS@ +XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ +XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ +XLIBGL_CFLAGS = @XLIBGL_CFLAGS@ +XLIBGL_LIBS = @XLIBGL_LIBS@ +XVMC_CFLAGS = @XVMC_CFLAGS@ +XVMC_LIBS = @XVMC_LIBS@ +XVMC_LIB_INSTALL_DIR = @XVMC_LIB_INSTALL_DIR@ +XVMC_MAJOR = @XVMC_MAJOR@ +XVMC_MINOR = @XVMC_MINOR@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acv_mako_found = @acv_mako_found@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ifGNUmake = @ifGNUmake@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gtest/include \ + $(PTHREAD_CFLAGS) \ + $(DEFINES) + +string_buffer_test_SOURCES = \ + string_buffer_test.cpp + +string_buffer_test_LDADD = \ + $(top_builddir)/src/gtest/libgtest.la \ + $(top_builddir)/src/util/libmesautil.la \ + $(PTHREAD_LIBS) \ + $(DLOPEN_LIBS) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/util/tests/string_buffer/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/util/tests/string_buffer/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +string_buffer_test$(EXEEXT): $(string_buffer_test_OBJECTS) $(string_buffer_test_DEPENDENCIES) $(EXTRA_string_buffer_test_DEPENDENCIES) + @rm -f string_buffer_test$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(string_buffer_test_OBJECTS) $(string_buffer_test_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string_buffer_test.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +string_buffer_test.log: string_buffer_test$(EXEEXT) + @p='string_buffer_test$(EXEEXT)'; \ + b='string_buffer_test'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/mesa/src/util/tests/string_buffer/string_buffer_test.cpp b/lib/mesa/src/util/tests/string_buffer/string_buffer_test.cpp new file mode 100644 index 000000000..545f607fa --- /dev/null +++ b/lib/mesa/src/util/tests/string_buffer/string_buffer_test.cpp @@ -0,0 +1,122 @@ +/* + * Copyright © 2017 Thomas Helland + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <gtest/gtest.h> +#include "util/string_buffer.h" + +/** + * \file string_buffer_test.cpp + * + * Test the string buffer implementation + */ + +#define INITIAL_BUF_SIZE 6 +class string_buffer : public ::testing::Test { +public: + + struct _mesa_string_buffer *buf; + const char *str1; + const char *str2; + const char *str3; + char str4[80]; + char str5[40]; + + virtual void SetUp(); + virtual void TearDown(); +}; + +void +string_buffer::SetUp() +{ + str1 = "test1"; + str2 = "test2"; + str3 = "test1test2"; + buf = _mesa_string_buffer_create(NULL, INITIAL_BUF_SIZE); +} + +void +string_buffer::TearDown() +{ + /* Finally, clean up after us */ + _mesa_string_buffer_destroy(buf); +} + +static uint32_t +space_left_in_buffer(_mesa_string_buffer *buf) +{ + return buf->capacity - buf->length - 1; +} + +TEST_F(string_buffer, string_buffer_tests) +{ + /* The string terminator needs one byte, so there should one "missing" */ + EXPECT_TRUE(space_left_in_buffer(buf) == INITIAL_BUF_SIZE - 1); + + /* Start by appending str1 */ + EXPECT_TRUE(_mesa_string_buffer_append(buf, str1)); + EXPECT_TRUE(space_left_in_buffer(buf) == + INITIAL_BUF_SIZE - strlen(str1) - 1); + EXPECT_TRUE(strcmp(buf->buf, str1) == 0); + + /* Add more, so that the string is resized */ + EXPECT_TRUE(_mesa_string_buffer_append(buf, str2)); + + /* The string should now be equal to str3 */ + EXPECT_TRUE(strcmp(buf->buf, str3) == 0); + + /* Check that the length of the string is reset when clearing */ + _mesa_string_buffer_clear(buf); + EXPECT_TRUE(buf->length == 0); + EXPECT_TRUE(strlen(buf->buf) == 0); + + /* Test a string with some formatting */ + sprintf(str4, "Testing formatting %d, %f", 100, 1.0); + EXPECT_TRUE(_mesa_string_buffer_printf(buf, "Testing formatting %d, %f", 100, 1.0)); + EXPECT_TRUE(strcmp(buf->buf, str4) == 0); + + /* Compile a string with some other formatting */ + sprintf(str5, "Testing formatting %d, %x", 100, 0xDEADBEAF); + + /* Concatenate str5 to str4 */ + strcat(str4, str5); + + /* Now use the formatted append function again */ + EXPECT_TRUE(_mesa_string_buffer_printf(buf, "Testing formatting %d, %x", 100, 0xDEADBEAF)); + + /* The string buffer should now be equal to str4 */ + EXPECT_TRUE(strcmp(buf->buf, str4) == 0); + + _mesa_string_buffer_clear(buf); + + /* Test appending by one char at a time */ + EXPECT_TRUE(_mesa_string_buffer_append_char(buf, 'a')); + EXPECT_TRUE(buf->length == 1); + EXPECT_TRUE(strcmp(buf->buf, "a") == 0); + EXPECT_TRUE(_mesa_string_buffer_append_char(buf, 'a')); + EXPECT_TRUE(strcmp(buf->buf, "aa") == 0); +} diff --git a/lib/mesa/src/util/xmlconfig.c b/lib/mesa/src/util/xmlconfig.c new file mode 100644 index 000000000..60a6331c8 --- /dev/null +++ b/lib/mesa/src/util/xmlconfig.c @@ -0,0 +1,1113 @@ +/* + * XML DRI client-side driver configuration + * Copyright (C) 2003 Felix Kuehling + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 + * FELIX KUEHLING, 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 xmlconfig.c + * \brief Driver-independent client-side part of the XML configuration + * \author Felix Kuehling + */ + +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <expat.h> +#include <fcntl.h> +#include <math.h> +#include <unistd.h> +#include <errno.h> +#include "xmlconfig.h" + +#undef GET_PROGRAM_NAME + +#if (defined(__GNU_LIBRARY__) || defined(__GLIBC__)) && !defined(__UCLIBC__) +# if !defined(__GLIBC__) || (__GLIBC__ < 2) +/* These aren't declared in any libc5 header */ +extern char *program_invocation_name, *program_invocation_short_name; +# endif +# define GET_PROGRAM_NAME() program_invocation_short_name +#elif defined(__CYGWIN__) +# define GET_PROGRAM_NAME() program_invocation_short_name +#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2) +# include <osreldate.h> +# if (__FreeBSD_version >= 440000) +# include <stdlib.h> +# define GET_PROGRAM_NAME() getprogname() +# endif +#elif defined(__NetBSD__) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000100) +# include <stdlib.h> +# define GET_PROGRAM_NAME() getprogname() +#elif defined(__DragonFly__) +# include <stdlib.h> +# define GET_PROGRAM_NAME() getprogname() +#elif defined(__APPLE__) +# include <stdlib.h> +# define GET_PROGRAM_NAME() getprogname() +#elif defined(__sun) +/* Solaris has getexecname() which returns the full path - return just + the basename to match BSD getprogname() */ +# include <stdlib.h> +# include <libgen.h> + +static const char * +__getProgramName() +{ + static const char *progname; + + if (progname == NULL) { + const char *e = getexecname(); + if (e != NULL) { + /* Have to make a copy since getexecname can return a readonly + string, but basename expects to be able to modify its arg. */ + char *n = strdup(e); + if (n != NULL) { + progname = basename(n); + } + } + } + return progname; +} + +# define GET_PROGRAM_NAME() __getProgramName() +#endif + +#if !defined(GET_PROGRAM_NAME) +# if defined(__OpenBSD__) || defined(NetBSD) || defined(__UCLIBC__) || defined(ANDROID) +/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU. + * Rogelio M.Serrano Jr. reported it's also working with UCLIBC. It's + * used as a last resort, if there is no documented facility available. */ +static const char * +__getProgramName() +{ + extern const char *__progname; + char * arg = strrchr(__progname, '/'); + if (arg) + return arg+1; + else + return __progname; +} +# define GET_PROGRAM_NAME() __getProgramName() +# else +# define GET_PROGRAM_NAME() "" +# warning "Per application configuration won't work with your OS version." +# endif +#endif + +/** \brief Find an option in an option cache with the name as key */ +static uint32_t +findOption(const driOptionCache *cache, const char *name) +{ + uint32_t len = strlen (name); + uint32_t size = 1 << cache->tableSize, mask = size - 1; + uint32_t hash = 0; + uint32_t i, shift; + + /* compute a hash from the variable length name */ + for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31) + hash += (uint32_t)name[i] << shift; + hash *= hash; + hash = (hash >> (16-cache->tableSize/2)) & mask; + + /* this is just the starting point of the linear search for the option */ + for (i = 0; i < size; ++i, hash = (hash+1) & mask) { + /* if we hit an empty entry then the option is not defined (yet) */ + if (cache->info[hash].name == 0) + break; + else if (!strcmp (name, cache->info[hash].name)) + break; + } + /* this assertion fails if the hash table is full */ + assert (i < size); + + return hash; +} + +/** \brief Like strdup but using malloc and with error checking. */ +#define XSTRDUP(dest,source) do { \ + uint32_t len = strlen (source); \ + if (!(dest = malloc(len+1))) { \ + fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \ + abort(); \ + } \ + memcpy (dest, source, len+1); \ +} while (0) + +static int compare (const void *a, const void *b) { + return strcmp (*(char *const*)a, *(char *const*)b); +} +/** \brief Binary search in a string array. */ +static uint32_t +bsearchStr (const XML_Char *name, const XML_Char *elems[], uint32_t count) +{ + const XML_Char **found; + found = bsearch (&name, elems, count, sizeof (XML_Char *), compare); + if (found) + return found - elems; + else + return count; +} + +/** \brief Locale-independent integer parser. + * + * Works similar to strtol. Leading space is NOT skipped. The input + * number may have an optional sign. Radix is specified by base. If + * base is 0 then decimal is assumed unless the input number is + * prefixed by 0x or 0X for hexadecimal or 0 for octal. After + * returning tail points to the first character that is not part of + * the integer number. If no number was found then tail points to the + * start of the input string. */ +static int +strToI(const XML_Char *string, const XML_Char **tail, int base) +{ + int radix = base == 0 ? 10 : base; + int result = 0; + int sign = 1; + bool numberFound = false; + const XML_Char *start = string; + + assert (radix >= 2 && radix <= 36); + + if (*string == '-') { + sign = -1; + string++; + } else if (*string == '+') + string++; + if (base == 0 && *string == '0') { + numberFound = true; + if (*(string+1) == 'x' || *(string+1) == 'X') { + radix = 16; + string += 2; + } else { + radix = 8; + string++; + } + } + do { + int digit = -1; + if (radix <= 10) { + if (*string >= '0' && *string < '0' + radix) + digit = *string - '0'; + } else { + if (*string >= '0' && *string <= '9') + digit = *string - '0'; + else if (*string >= 'a' && *string < 'a' + radix - 10) + digit = *string - 'a' + 10; + else if (*string >= 'A' && *string < 'A' + radix - 10) + digit = *string - 'A' + 10; + } + if (digit != -1) { + numberFound = true; + result = radix*result + digit; + string++; + } else + break; + } while (true); + *tail = numberFound ? string : start; + return sign * result; +} + +/** \brief Locale-independent floating-point parser. + * + * Works similar to strtod. Leading space is NOT skipped. The input + * number may have an optional sign. '.' is interpreted as decimal + * point and may occur at most once. Optionally the number may end in + * [eE]<exponent>, where <exponent> is an integer as recognized by + * strToI. In that case the result is number * 10^exponent. After + * returning tail points to the first character that is not part of + * the floating point number. If no number was found then tail points + * to the start of the input string. + * + * Uses two passes for maximum accuracy. */ +static float +strToF(const XML_Char *string, const XML_Char **tail) +{ + int nDigits = 0, pointPos, exponent; + float sign = 1.0f, result = 0.0f, scale; + const XML_Char *start = string, *numStart; + + /* sign */ + if (*string == '-') { + sign = -1.0f; + string++; + } else if (*string == '+') + string++; + + /* first pass: determine position of decimal point, number of + * digits, exponent and the end of the number. */ + numStart = string; + while (*string >= '0' && *string <= '9') { + string++; + nDigits++; + } + pointPos = nDigits; + if (*string == '.') { + string++; + while (*string >= '0' && *string <= '9') { + string++; + nDigits++; + } + } + if (nDigits == 0) { + /* no digits, no number */ + *tail = start; + return 0.0f; + } + *tail = string; + if (*string == 'e' || *string == 'E') { + const XML_Char *expTail; + exponent = strToI (string+1, &expTail, 10); + if (expTail == string+1) + exponent = 0; + else + *tail = expTail; + } else + exponent = 0; + string = numStart; + + /* scale of the first digit */ + scale = sign * (float)pow (10.0, (double)(pointPos-1 + exponent)); + + /* second pass: parse digits */ + do { + if (*string != '.') { + assert (*string >= '0' && *string <= '9'); + result += scale * (float)(*string - '0'); + scale *= 0.1f; + nDigits--; + } + string++; + } while (nDigits > 0); + + return result; +} + +/** \brief Parse a value of a given type. */ +static unsigned char +parseValue(driOptionValue *v, driOptionType type, const XML_Char *string) +{ + const XML_Char *tail = NULL; + /* skip leading white-space */ + string += strspn (string, " \f\n\r\t\v"); + switch (type) { + case DRI_BOOL: + if (!strcmp (string, "false")) { + v->_bool = false; + tail = string + 5; + } else if (!strcmp (string, "true")) { + v->_bool = true; + tail = string + 4; + } + else + return false; + break; + case DRI_ENUM: /* enum is just a special integer */ + case DRI_INT: + v->_int = strToI (string, &tail, 0); + break; + case DRI_FLOAT: + v->_float = strToF (string, &tail); + break; + case DRI_STRING: + free (v->_string); + v->_string = strndup(string, STRING_CONF_MAXLEN); + return true; + } + + if (tail == string) + return false; /* empty string (or containing only white-space) */ + /* skip trailing white space */ + if (*tail) + tail += strspn (tail, " \f\n\r\t\v"); + if (*tail) + return false; /* something left over that is not part of value */ + + return true; +} + +/** \brief Parse a list of ranges of type info->type. */ +static unsigned char +parseRanges(driOptionInfo *info, const XML_Char *string) +{ + XML_Char *cp, *range; + uint32_t nRanges, i; + driOptionRange *ranges; + + XSTRDUP (cp, string); + /* pass 1: determine the number of ranges (number of commas + 1) */ + range = cp; + for (nRanges = 1; *range; ++range) + if (*range == ',') + ++nRanges; + + if ((ranges = malloc(nRanges*sizeof(driOptionRange))) == NULL) { + fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); + abort(); + } + + /* pass 2: parse all ranges into preallocated array */ + range = cp; + for (i = 0; i < nRanges; ++i) { + XML_Char *end, *sep; + assert (range); + end = strchr (range, ','); + if (end) + *end = '\0'; + sep = strchr (range, ':'); + if (sep) { /* non-empty interval */ + *sep = '\0'; + if (!parseValue (&ranges[i].start, info->type, range) || + !parseValue (&ranges[i].end, info->type, sep+1)) + break; + if (info->type == DRI_INT && + ranges[i].start._int > ranges[i].end._int) + break; + if (info->type == DRI_FLOAT && + ranges[i].start._float > ranges[i].end._float) + break; + } else { /* empty interval */ + if (!parseValue (&ranges[i].start, info->type, range)) + break; + ranges[i].end = ranges[i].start; + } + if (end) + range = end+1; + else + range = NULL; + } + free(cp); + if (i < nRanges) { + free(ranges); + return false; + } else + assert (range == NULL); + + info->nRanges = nRanges; + info->ranges = ranges; + return true; +} + +/** \brief Check if a value is in one of info->ranges. */ +static bool +checkValue(const driOptionValue *v, const driOptionInfo *info) +{ + uint32_t i; + assert (info->type != DRI_BOOL); /* should be caught by the parser */ + if (info->nRanges == 0) + return true; + switch (info->type) { + case DRI_ENUM: /* enum is just a special integer */ + case DRI_INT: + for (i = 0; i < info->nRanges; ++i) + if (v->_int >= info->ranges[i].start._int && + v->_int <= info->ranges[i].end._int) + return true; + break; + case DRI_FLOAT: + for (i = 0; i < info->nRanges; ++i) + if (v->_float >= info->ranges[i].start._float && + v->_float <= info->ranges[i].end._float) + return true; + break; + case DRI_STRING: + break; + default: + assert (0); /* should never happen */ + } + return false; +} + +/** + * Print message to \c stderr if the \c LIBGL_DEBUG environment variable + * is set. + * + * Is called from the drivers. + * + * \param f \c printf like format string. + */ +static void +__driUtilMessage(const char *f, ...) +{ + va_list args; + const char *libgl_debug; + + libgl_debug=getenv("LIBGL_DEBUG"); + if (libgl_debug && !strstr(libgl_debug, "quiet")) { + fprintf(stderr, "libGL: "); + va_start(args, f); + vfprintf(stderr, f, args); + va_end(args); + fprintf(stderr, "\n"); + } +} + +/** \brief Output a warning message. */ +#define XML_WARNING1(msg) do {\ + __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ + (int) XML_GetCurrentLineNumber(data->parser), \ + (int) XML_GetCurrentColumnNumber(data->parser)); \ +} while (0) +#define XML_WARNING(msg, ...) do { \ + __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \ + (int) XML_GetCurrentLineNumber(data->parser), \ + (int) XML_GetCurrentColumnNumber(data->parser), \ + ##__VA_ARGS__); \ +} while (0) +/** \brief Output an error message. */ +#define XML_ERROR1(msg) do { \ + __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ + (int) XML_GetCurrentLineNumber(data->parser), \ + (int) XML_GetCurrentColumnNumber(data->parser)); \ +} while (0) +#define XML_ERROR(msg, ...) do { \ + __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \ + (int) XML_GetCurrentLineNumber(data->parser), \ + (int) XML_GetCurrentColumnNumber(data->parser), \ + ##__VA_ARGS__); \ +} while (0) +/** \brief Output a fatal error message and abort. */ +#define XML_FATAL1(msg) do { \ + fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ + data->name, \ + (int) XML_GetCurrentLineNumber(data->parser), \ + (int) XML_GetCurrentColumnNumber(data->parser)); \ + abort();\ +} while (0) +#define XML_FATAL(msg, ...) do { \ + fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \ + data->name, \ + (int) XML_GetCurrentLineNumber(data->parser), \ + (int) XML_GetCurrentColumnNumber(data->parser), \ + ##__VA_ARGS__); \ + abort();\ +} while (0) + +/** \brief Parser context for __driConfigOptions. */ +struct OptInfoData { + const char *name; + XML_Parser parser; + driOptionCache *cache; + bool inDriInfo; + bool inSection; + bool inDesc; + bool inOption; + bool inEnum; + int curOption; +}; + +/** \brief Elements in __driConfigOptions. */ +enum OptInfoElem { + OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT +}; +static const XML_Char *OptInfoElems[] = { + "description", "driinfo", "enum", "option", "section" +}; + +/** \brief Parse attributes of an enum element. + * + * We're not actually interested in the data. Just make sure this is ok + * for external configuration tools. + */ +static void +parseEnumAttr(struct OptInfoData *data, const XML_Char **attr) +{ + uint32_t i; + const XML_Char *value = NULL, *text = NULL; + driOptionValue v; + uint32_t opt = data->curOption; + for (i = 0; attr[i]; i += 2) { + if (!strcmp (attr[i], "value")) value = attr[i+1]; + else if (!strcmp (attr[i], "text")) text = attr[i+1]; + else XML_FATAL("illegal enum attribute: %s.", attr[i]); + } + if (!value) XML_FATAL1 ("value attribute missing in enum."); + if (!text) XML_FATAL1 ("text attribute missing in enum."); + if (!parseValue (&v, data->cache->info[opt].type, value)) + XML_FATAL ("illegal enum value: %s.", value); + if (!checkValue (&v, &data->cache->info[opt])) + XML_FATAL ("enum value out of valid range: %s.", value); +} + +/** \brief Parse attributes of a description element. + * + * We're not actually interested in the data. Just make sure this is ok + * for external configuration tools. + */ +static void +parseDescAttr(struct OptInfoData *data, const XML_Char **attr) +{ + uint32_t i; + const XML_Char *lang = NULL, *text = NULL; + for (i = 0; attr[i]; i += 2) { + if (!strcmp (attr[i], "lang")) lang = attr[i+1]; + else if (!strcmp (attr[i], "text")) text = attr[i+1]; + else XML_FATAL("illegal description attribute: %s.", attr[i]); + } + if (!lang) XML_FATAL1 ("lang attribute missing in description."); + if (!text) XML_FATAL1 ("text attribute missing in description."); +} + +/** \brief Parse attributes of an option element. */ +static void +parseOptInfoAttr(struct OptInfoData *data, const XML_Char **attr) +{ + enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT}; + static const XML_Char *optAttr[] = {"default", "name", "type", "valid"}; + const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL}; + const char *defaultVal; + driOptionCache *cache = data->cache; + uint32_t opt, i; + for (i = 0; attr[i]; i += 2) { + uint32_t attrName = bsearchStr (attr[i], optAttr, OA_COUNT); + if (attrName >= OA_COUNT) + XML_FATAL ("illegal option attribute: %s", attr[i]); + attrVal[attrName] = attr[i+1]; + } + if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option."); + if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option."); + if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option."); + + opt = findOption (cache, attrVal[OA_NAME]); + if (cache->info[opt].name) + XML_FATAL ("option %s redefined.", attrVal[OA_NAME]); + data->curOption = opt; + + XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]); + + if (!strcmp (attrVal[OA_TYPE], "bool")) + cache->info[opt].type = DRI_BOOL; + else if (!strcmp (attrVal[OA_TYPE], "enum")) + cache->info[opt].type = DRI_ENUM; + else if (!strcmp (attrVal[OA_TYPE], "int")) + cache->info[opt].type = DRI_INT; + else if (!strcmp (attrVal[OA_TYPE], "float")) + cache->info[opt].type = DRI_FLOAT; + else if (!strcmp (attrVal[OA_TYPE], "string")) + cache->info[opt].type = DRI_STRING; + else + XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]); + + defaultVal = getenv (cache->info[opt].name); + if (defaultVal != NULL) { + /* don't use XML_WARNING, we want the user to see this! */ + fprintf (stderr, + "ATTENTION: default value of option %s overridden by environment.\n", + cache->info[opt].name); + } else + defaultVal = attrVal[OA_DEFAULT]; + if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal)) + XML_FATAL ("illegal default value for %s: %s.", cache->info[opt].name, defaultVal); + + if (attrVal[OA_VALID]) { + if (cache->info[opt].type == DRI_BOOL) + XML_FATAL1 ("boolean option with valid attribute."); + if (!parseRanges (&cache->info[opt], attrVal[OA_VALID])) + XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]); + if (!checkValue (&cache->values[opt], &cache->info[opt])) + XML_FATAL ("default value out of valid range '%s': %s.", + attrVal[OA_VALID], defaultVal); + } else if (cache->info[opt].type == DRI_ENUM) { + XML_FATAL1 ("valid attribute missing in option (mandatory for enums)."); + } else { + cache->info[opt].nRanges = 0; + cache->info[opt].ranges = NULL; + } +} + +/** \brief Handler for start element events. */ +static void +optInfoStartElem(void *userData, const XML_Char *name, const XML_Char **attr) +{ + struct OptInfoData *data = (struct OptInfoData *)userData; + enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT); + switch (elem) { + case OI_DRIINFO: + if (data->inDriInfo) + XML_FATAL1 ("nested <driinfo> elements."); + if (attr[0]) + XML_FATAL1 ("attributes specified on <driinfo> element."); + data->inDriInfo = true; + break; + case OI_SECTION: + if (!data->inDriInfo) + XML_FATAL1 ("<section> must be inside <driinfo>."); + if (data->inSection) + XML_FATAL1 ("nested <section> elements."); + if (attr[0]) + XML_FATAL1 ("attributes specified on <section> element."); + data->inSection = true; + break; + case OI_DESCRIPTION: + if (!data->inSection && !data->inOption) + XML_FATAL1 ("<description> must be inside <description> or <option."); + if (data->inDesc) + XML_FATAL1 ("nested <description> elements."); + data->inDesc = true; + parseDescAttr (data, attr); + break; + case OI_OPTION: + if (!data->inSection) + XML_FATAL1 ("<option> must be inside <section>."); + if (data->inDesc) + XML_FATAL1 ("<option> nested in <description> element."); + if (data->inOption) + XML_FATAL1 ("nested <option> elements."); + data->inOption = true; + parseOptInfoAttr (data, attr); + break; + case OI_ENUM: + if (!(data->inOption && data->inDesc)) + XML_FATAL1 ("<enum> must be inside <option> and <description>."); + if (data->inEnum) + XML_FATAL1 ("nested <enum> elements."); + data->inEnum = true; + parseEnumAttr (data, attr); + break; + default: + XML_FATAL ("unknown element: %s.", name); + } +} + +/** \brief Handler for end element events. */ +static void +optInfoEndElem(void *userData, const XML_Char *name) +{ + struct OptInfoData *data = (struct OptInfoData *)userData; + enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT); + switch (elem) { + case OI_DRIINFO: + data->inDriInfo = false; + break; + case OI_SECTION: + data->inSection = false; + break; + case OI_DESCRIPTION: + data->inDesc = false; + break; + case OI_OPTION: + data->inOption = false; + break; + case OI_ENUM: + data->inEnum = false; + break; + default: + assert (0); /* should have been caught by StartElem */ + } +} + +void +driParseOptionInfo(driOptionCache *info, const char *configOptions) +{ + XML_Parser p; + int status; + struct OptInfoData userData; + struct OptInfoData *data = &userData; + + /* Make the hash table big enough to fit more than the maximum number of + * config options we've ever seen in a driver. + */ + info->tableSize = 6; + info->info = calloc(1 << info->tableSize, sizeof (driOptionInfo)); + info->values = calloc(1 << info->tableSize, sizeof (driOptionValue)); + if (info->info == NULL || info->values == NULL) { + fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); + abort(); + } + + p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */ + XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem); + XML_SetUserData (p, data); + + userData.name = "__driConfigOptions"; + userData.parser = p; + userData.cache = info; + userData.inDriInfo = false; + userData.inSection = false; + userData.inDesc = false; + userData.inOption = false; + userData.inEnum = false; + userData.curOption = -1; + + status = XML_Parse (p, configOptions, strlen (configOptions), 1); + if (!status) + XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p))); + + XML_ParserFree (p); +} + +/** \brief Parser context for configuration files. */ +struct OptConfData { + const char *name; + XML_Parser parser; + driOptionCache *cache; + int screenNum; + const char *driverName, *execName; + uint32_t ignoringDevice; + uint32_t ignoringApp; + uint32_t inDriConf; + uint32_t inDevice; + uint32_t inApp; + uint32_t inOption; +}; + +/** \brief Elements in configuration files. */ +enum OptConfElem { + OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT +}; +static const XML_Char *OptConfElems[] = { + [OC_APPLICATION] = "application", + [OC_DEVICE] = "device", + [OC_DRICONF] = "driconf", + [OC_OPTION] = "option", +}; + +/** \brief Parse attributes of a device element. */ +static void +parseDeviceAttr(struct OptConfData *data, const XML_Char **attr) +{ + uint32_t i; + const XML_Char *driver = NULL, *screen = NULL; + for (i = 0; attr[i]; i += 2) { + if (!strcmp (attr[i], "driver")) driver = attr[i+1]; + else if (!strcmp (attr[i], "screen")) screen = attr[i+1]; + else XML_WARNING("unknown device attribute: %s.", attr[i]); + } + if (driver && strcmp (driver, data->driverName)) + data->ignoringDevice = data->inDevice; + else if (screen) { + driOptionValue screenNum; + if (!parseValue (&screenNum, DRI_INT, screen)) + XML_WARNING("illegal screen number: %s.", screen); + else if (screenNum._int != data->screenNum) + data->ignoringDevice = data->inDevice; + } +} + +/** \brief Parse attributes of an application element. */ +static void +parseAppAttr(struct OptConfData *data, const XML_Char **attr) +{ + uint32_t i; + const XML_Char *exec = NULL; + for (i = 0; attr[i]; i += 2) { + if (!strcmp (attr[i], "name")) /* not needed here */; + else if (!strcmp (attr[i], "executable")) exec = attr[i+1]; + else XML_WARNING("unknown application attribute: %s.", attr[i]); + } + if (exec && strcmp (exec, data->execName)) + data->ignoringApp = data->inApp; +} + +/** \brief Parse attributes of an option element. */ +static void +parseOptConfAttr(struct OptConfData *data, const XML_Char **attr) +{ + uint32_t i; + const XML_Char *name = NULL, *value = NULL; + for (i = 0; attr[i]; i += 2) { + if (!strcmp (attr[i], "name")) name = attr[i+1]; + else if (!strcmp (attr[i], "value")) value = attr[i+1]; + else XML_WARNING("unknown option attribute: %s.", attr[i]); + } + if (!name) XML_WARNING1 ("name attribute missing in option."); + if (!value) XML_WARNING1 ("value attribute missing in option."); + if (name && value) { + driOptionCache *cache = data->cache; + uint32_t opt = findOption (cache, name); + if (cache->info[opt].name == NULL) + /* don't use XML_WARNING, drirc defines options for all drivers, + * but not all drivers support them */ + return; + else if (getenv (cache->info[opt].name)) + /* don't use XML_WARNING, we want the user to see this! */ + fprintf (stderr, "ATTENTION: option value of option %s ignored.\n", + cache->info[opt].name); + else if (!parseValue (&cache->values[opt], cache->info[opt].type, value)) + XML_WARNING ("illegal option value: %s.", value); + } +} + +/** \brief Handler for start element events. */ +static void +optConfStartElem(void *userData, const XML_Char *name, + const XML_Char **attr) +{ + struct OptConfData *data = (struct OptConfData *)userData; + enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT); + switch (elem) { + case OC_DRICONF: + if (data->inDriConf) + XML_WARNING1 ("nested <driconf> elements."); + if (attr[0]) + XML_WARNING1 ("attributes specified on <driconf> element."); + data->inDriConf++; + break; + case OC_DEVICE: + if (!data->inDriConf) + XML_WARNING1 ("<device> should be inside <driconf>."); + if (data->inDevice) + XML_WARNING1 ("nested <device> elements."); + data->inDevice++; + if (!data->ignoringDevice && !data->ignoringApp) + parseDeviceAttr (data, attr); + break; + case OC_APPLICATION: + if (!data->inDevice) + XML_WARNING1 ("<application> should be inside <device>."); + if (data->inApp) + XML_WARNING1 ("nested <application> elements."); + data->inApp++; + if (!data->ignoringDevice && !data->ignoringApp) + parseAppAttr (data, attr); + break; + case OC_OPTION: + if (!data->inApp) + XML_WARNING1 ("<option> should be inside <application>."); + if (data->inOption) + XML_WARNING1 ("nested <option> elements."); + data->inOption++; + if (!data->ignoringDevice && !data->ignoringApp) + parseOptConfAttr (data, attr); + break; + default: + XML_WARNING ("unknown element: %s.", name); + } +} + +/** \brief Handler for end element events. */ +static void +optConfEndElem(void *userData, const XML_Char *name) +{ + struct OptConfData *data = (struct OptConfData *)userData; + enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT); + switch (elem) { + case OC_DRICONF: + data->inDriConf--; + break; + case OC_DEVICE: + if (data->inDevice-- == data->ignoringDevice) + data->ignoringDevice = 0; + break; + case OC_APPLICATION: + if (data->inApp-- == data->ignoringApp) + data->ignoringApp = 0; + break; + case OC_OPTION: + data->inOption--; + break; + default: + /* unknown element, warning was produced on start tag */; + } +} + +/** \brief Initialize an option cache based on info */ +static void +initOptionCache(driOptionCache *cache, const driOptionCache *info) +{ + unsigned i, size = 1 << info->tableSize; + cache->info = info->info; + cache->tableSize = info->tableSize; + cache->values = malloc((1<<info->tableSize) * sizeof (driOptionValue)); + if (cache->values == NULL) { + fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); + abort(); + } + memcpy (cache->values, info->values, + (1<<info->tableSize) * sizeof (driOptionValue)); + for (i = 0; i < size; ++i) { + if (cache->info[i].type == DRI_STRING) + XSTRDUP(cache->values[i]._string, info->values[i]._string); + } +} + +/** \brief Parse the named configuration file */ +static void +parseOneConfigFile(XML_Parser p) +{ +#define BUF_SIZE 0x1000 + struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p); + int status; + int fd; + + if ((fd = open (data->name, O_RDONLY)) == -1) { + __driUtilMessage ("Can't open configuration file %s: %s.", + data->name, strerror (errno)); + return; + } + + while (1) { + int bytesRead; + void *buffer = XML_GetBuffer (p, BUF_SIZE); + if (!buffer) { + __driUtilMessage ("Can't allocate parser buffer."); + break; + } + bytesRead = read (fd, buffer, BUF_SIZE); + if (bytesRead == -1) { + __driUtilMessage ("Error reading from configuration file %s: %s.", + data->name, strerror (errno)); + break; + } + status = XML_ParseBuffer (p, bytesRead, bytesRead == 0); + if (!status) { + XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p))); + break; + } + if (bytesRead == 0) + break; + } + + close (fd); +#undef BUF_SIZE +} + +#ifndef SYSCONFDIR +#define SYSCONFDIR "/etc" +#endif + +void +driParseConfigFiles(driOptionCache *cache, const driOptionCache *info, + int screenNum, const char *driverName) +{ + char *filenames[2] = { SYSCONFDIR "/drirc", NULL}; + char *home; + uint32_t i; + struct OptConfData userData; + + initOptionCache (cache, info); + + userData.cache = cache; + userData.screenNum = screenNum; + userData.driverName = driverName; + userData.execName = GET_PROGRAM_NAME(); + + if ((home = getenv ("HOME"))) { + uint32_t len = strlen (home); + filenames[1] = malloc(len + 7+1); + if (filenames[1] == NULL) + __driUtilMessage ("Can't allocate memory for %s/.drirc.", home); + else { + memcpy (filenames[1], home, len); + memcpy (filenames[1] + len, "/.drirc", 7+1); + } + } + + for (i = 0; i < 2; ++i) { + XML_Parser p; + if (filenames[i] == NULL) + continue; + + p = XML_ParserCreate (NULL); /* use encoding specified by file */ + XML_SetElementHandler (p, optConfStartElem, optConfEndElem); + XML_SetUserData (p, &userData); + userData.parser = p; + userData.name = filenames[i]; + userData.ignoringDevice = 0; + userData.ignoringApp = 0; + userData.inDriConf = 0; + userData.inDevice = 0; + userData.inApp = 0; + userData.inOption = 0; + + parseOneConfigFile (p); + XML_ParserFree (p); + } + + free(filenames[1]); +} + +void +driDestroyOptionInfo(driOptionCache *info) +{ + driDestroyOptionCache(info); + if (info->info) { + uint32_t i, size = 1 << info->tableSize; + for (i = 0; i < size; ++i) { + if (info->info[i].name) { + free(info->info[i].name); + free(info->info[i].ranges); + } + } + free(info->info); + } +} + +void +driDestroyOptionCache(driOptionCache *cache) +{ + if (cache->info) { + unsigned i, size = 1 << cache->tableSize; + for (i = 0; i < size; ++i) { + if (cache->info[i].type == DRI_STRING) + free(cache->values[i]._string); + } + } + free(cache->values); +} + +unsigned char +driCheckOption(const driOptionCache *cache, const char *name, + driOptionType type) +{ + uint32_t i = findOption (cache, name); + return cache->info[i].name != NULL && cache->info[i].type == type; +} + +unsigned char +driQueryOptionb(const driOptionCache *cache, const char *name) +{ + uint32_t i = findOption (cache, name); + /* make sure the option is defined and has the correct type */ + assert (cache->info[i].name != NULL); + assert (cache->info[i].type == DRI_BOOL); + return cache->values[i]._bool; +} + +int +driQueryOptioni(const driOptionCache *cache, const char *name) +{ + uint32_t i = findOption (cache, name); + /* make sure the option is defined and has the correct type */ + assert (cache->info[i].name != NULL); + assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM); + return cache->values[i]._int; +} + +float +driQueryOptionf(const driOptionCache *cache, const char *name) +{ + uint32_t i = findOption (cache, name); + /* make sure the option is defined and has the correct type */ + assert (cache->info[i].name != NULL); + assert (cache->info[i].type == DRI_FLOAT); + return cache->values[i]._float; +} + +char * +driQueryOptionstr(const driOptionCache *cache, const char *name) +{ + uint32_t i = findOption (cache, name); + /* make sure the option is defined and has the correct type */ + assert (cache->info[i].name != NULL); + assert (cache->info[i].type == DRI_STRING); + return cache->values[i]._string; +} diff --git a/lib/mesa/src/util/xmlconfig.h b/lib/mesa/src/util/xmlconfig.h new file mode 100644 index 000000000..77aa14c20 --- /dev/null +++ b/lib/mesa/src/util/xmlconfig.h @@ -0,0 +1,179 @@ +/* + * XML DRI client-side driver configuration + * Copyright (C) 2003 Felix Kuehling + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 + * FELIX KUEHLING, 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 xmlconfig.h + * \brief Driver-independent client-side part of the XML configuration + * \author Felix Kuehling + */ + +#ifndef __XMLCONFIG_H +#define __XMLCONFIG_H + +#include "util/mesa-sha1.h" +#include "util/ralloc.h" + +#define STRING_CONF_MAXLEN 25 + +/** \brief Option data types */ +typedef enum driOptionType { + DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT, DRI_STRING +} driOptionType; + +/** \brief Option value */ +typedef union driOptionValue { + unsigned char _bool; /**< \brief Boolean */ + int _int; /**< \brief Integer or Enum */ + float _float; /**< \brief Floating-point */ + char *_string; /**< \brief String */ +} driOptionValue; + +/** \brief Single range of valid values + * + * For empty ranges (a single value) start == end */ +typedef struct driOptionRange { + driOptionValue start; /**< \brief Start */ + driOptionValue end; /**< \brief End */ +} driOptionRange; + +/** \brief Information about an option */ +typedef struct driOptionInfo { + char *name; /**< \brief Name */ + driOptionType type; /**< \brief Type */ + driOptionRange *ranges; /**< \brief Array of ranges */ + unsigned int nRanges; /**< \brief Number of ranges */ +} driOptionInfo; + +/** \brief Option cache + * + * \li One in <driver>Screen caching option info and the default values + * \li One in each <driver>Context with the actual values for that context */ +typedef struct driOptionCache { + driOptionInfo *info; + /**< \brief Array of option infos + * + * Points to the same array in the screen and all contexts */ + driOptionValue *values; + /**< \brief Array of option values + * + * \li Default values in screen + * \li Actual values in contexts + */ + unsigned int tableSize; + /**< \brief Size of the arrays + * + * In the current implementation it's not actually a size but log2(size). + * The value is the same in the screen and all contexts. */ +} driOptionCache; + +/** \brief Parse XML option info from configOptions + * + * To be called in <driver>CreateScreen + * + * \param info pointer to a driOptionCache that will store the option info + * \param configOptions XML document describing available configuration opts + * + * For the option information to be available to external configuration tools + * it must be a public symbol __driConfigOptions. It is also passed as a + * parameter to driParseOptionInfo in order to avoid driver-independent code + * depending on symbols in driver-specific code. */ +void driParseOptionInfo (driOptionCache *info, + const char *configOptions); +/** \brief Initialize option cache from info and parse configuration files + * + * To be called in <driver>CreateContext. screenNum and driverName select + * device sections. */ +void driParseConfigFiles (driOptionCache *cache, const driOptionCache *info, + int screenNum, const char *driverName); +/** \brief Destroy option info + * + * To be called in <driver>DestroyScreen */ +void driDestroyOptionInfo (driOptionCache *info); +/** \brief Destroy option cache + * + * To be called in <driver>DestroyContext */ +void driDestroyOptionCache (driOptionCache *cache); + +/** \brief Check if there exists a certain option */ +unsigned char driCheckOption (const driOptionCache *cache, const char *name, + driOptionType type); + +/** \brief Query a boolean option value */ +unsigned char driQueryOptionb (const driOptionCache *cache, const char *name); +/** \brief Query an integer option value */ +int driQueryOptioni (const driOptionCache *cache, const char *name); +/** \brief Query a floating-point option value */ +float driQueryOptionf (const driOptionCache *cache, const char *name); +/** \brief Query a string option value */ +char *driQueryOptionstr (const driOptionCache *cache, const char *name); + +/** + * Returns a hash of the options for this application. + */ +static inline void +driComputeOptionsSha1(const driOptionCache *cache, unsigned char *sha1) +{ + void *ctx = ralloc_context(NULL); + char *dri_options = ralloc_strdup(ctx, ""); + + for (int i = 0; i < 1 << cache->tableSize; i++) { + if (cache->info[i].name == NULL) + continue; + + bool ret = false; + switch (cache->info[i].type) { + case DRI_BOOL: + ret = ralloc_asprintf_append(&dri_options, "%s:%u,", + cache->info[i].name, + cache->values[i]._bool); + break; + case DRI_INT: + case DRI_ENUM: + ret = ralloc_asprintf_append(&dri_options, "%s:%d,", + cache->info[i].name, + cache->values[i]._int); + break; + case DRI_FLOAT: + ret = ralloc_asprintf_append(&dri_options, "%s:%f,", + cache->info[i].name, + cache->values[i]._float); + break; + case DRI_STRING: + ret = ralloc_asprintf_append(&dri_options, "%s:%s,", + cache->info[i].name, + cache->values[i]._string); + break; + default: + unreachable("unsupported dri config type!"); + } + + if (!ret) { + break; + } + } + + _mesa_sha1_compute(dri_options, strlen(dri_options), sha1); + ralloc_free(ctx); +} + +#endif diff --git a/lib/mesa/src/util/xmlpool.h b/lib/mesa/src/util/xmlpool.h new file mode 100644 index 000000000..ebd4e7c86 --- /dev/null +++ b/lib/mesa/src/util/xmlpool.h @@ -0,0 +1,105 @@ +/* + * XML DRI client-side driver configuration + * Copyright (C) 2003 Felix Kuehling + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 + * FELIX KUEHLING, 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 xmlpool.h + * \brief Pool of common options + * \author Felix Kuehling + * + * This file defines macros that can be used to construct + * driConfigOptions in the drivers. Common options are defined in + * xmlpool/t_options.h from which xmlpool/options.h is generated with + * translations. This file defines generic helper macros and includes + * xmlpool/options.h. + */ + +#ifndef __XMLPOOL_H +#define __XMLPOOL_H + +/* + * generic macros + */ + +/** \brief Begin __driConfigOptions */ +#define DRI_CONF_BEGIN \ +"<driinfo>\n" + +/** \brief End __driConfigOptions */ +#define DRI_CONF_END \ +"</driinfo>\n" + +/** \brief Begin a section of related options */ +#define DRI_CONF_SECTION_BEGIN \ +"<section>\n" + +/** \brief End a section of related options */ +#define DRI_CONF_SECTION_END \ +"</section>\n" + +/** \brief Begin an option definition */ +#define DRI_CONF_OPT_BEGIN(name,type,def) \ +"<option name=\""#name"\" type=\""#type"\" default=\""#def"\">\n" + +/** + * \brief Begin a boolean option definition, with the default value passed in + * as a string + */ +#define DRI_CONF_OPT_BEGIN_B(name,def) \ +"<option name=\""#name"\" type=\"bool\" default="#def">\n" + +/** \brief Begin an option definition with quoted default value */ +#define DRI_CONF_OPT_BEGIN_Q(name,type,def) \ +"<option name=\""#name"\" type=\""#type"\" default="#def">\n" + +/** \brief Begin an option definition with restrictions on valid values */ +#define DRI_CONF_OPT_BEGIN_V(name,type,def,valid) \ +"<option name=\""#name"\" type=\""#type"\" default=\""#def"\" valid=\""valid"\">\n" + +/** \brief End an option description */ +#define DRI_CONF_OPT_END \ +"</option>\n" + +/** \brief A verbal description in a specified language (empty version) */ +#define DRI_CONF_DESC(lang,text) \ +"<description lang=\""#lang"\" text=\""text"\"/>\n" + +/** \brief A verbal description in a specified language */ +#define DRI_CONF_DESC_BEGIN(lang,text) \ +"<description lang=\""#lang"\" text=\""text"\">\n" + +/** \brief End a description */ +#define DRI_CONF_DESC_END \ +"</description>\n" + +/** \brief A verbal description of an enum value */ +#define DRI_CONF_ENUM(value,text) \ +"<enum value=\""#value"\" text=\""text"\"/>\n" + + +/* + * Predefined option sections and options with multi-lingual descriptions + * are now automatically generated. + */ +#include "xmlpool/options.h" + +#endif diff --git a/lib/mesa/src/util/xmlpool/Makefile.am b/lib/mesa/src/util/xmlpool/Makefile.am new file mode 100644 index 000000000..dfd8fb8dc --- /dev/null +++ b/lib/mesa/src/util/xmlpool/Makefile.am @@ -0,0 +1,101 @@ +# Convenient makefile for managing translations. + +# Prerequisites: +# - GNU gettext +# - Python + +# Adding new translations +# ----------------------- + +# To start working on a new translation edit the POS=... line +# below. If you want to add for example a french translation, add +# fr.po. + +# Then run "make po" to generate a fresh .po file from translatable +# strings in t_options.h. Now you can edit the new .po file (fr.po in +# the example above) to translate the strings. Please make sure that +# your editor encodes the file in UTF-8. + +# Updating existing translations +# ------------------------------ + +# Run "make po" to update .po files with new translatable strings from +# t_options.h. Now you can edit the .po files you're interested +# in. Please make sure that your editor encodes the file in UTF-8. + +# Updating options.h +# ------------------ + +# Finally run "make" to generate options.h from t_options.h with all +# translations. Now you can rebuild the drivers. Any common options +# used by the drivers will have option descriptions with the latest +# translations. + +# Publishing translations +# ----------------------- + +# To get your translation(s) into Mesa CVS, please send me your +# <lang>.po file. + +# More information: +# - info gettext + +# The set of supported languages. Add languages as needed. +POS=ca.po de.po es.po nl.po fr.po sv.po + +# +# Don't change anything below, unless you know what you're doing. +# +LANGS=$(POS:%.po=%) +MOS=$(POS:%.po=%/LC_MESSAGES/options.mo) +POT=xmlpool.pot + +.PHONY: all clean pot po mo + +EXTRA_DIST = \ + gen_xmlpool.py \ + options.h \ + t_options.h \ + $(POS) \ + $(MOS) \ + SConscript + +BUILT_SOURCES = options.h +CLEANFILES = \ + options.h + $(POS) \ + $(MOS) + +# Default target options.h +LOCALEDIR := . +options.h: t_options.h $(MOS) + $(AM_V_GEN) $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/gen_xmlpool.py $(srcdir)/t_options.h $(LOCALEDIR) $(LANGS) > options.h + +# Update .mo files from the corresponding .po files. +%/LC_MESSAGES/options.mo: %.po + @mo="$@"; \ + lang=$${mo%%/*}; \ + echo "Updating ($$lang) $@ from $?."; \ + $(MKDIR_P) $$lang/LC_MESSAGES; \ + msgfmt -o $@ $? + +# Use this target to create or update .po files with new messages in +# driconf.py. +po: $(POT) + @for po in $(POS); do \ + if [ -f $$po ]; then \ + echo "Merging new strings from $(POT) into $@."; \ + mv $$po $$po~; \ + msgmerge -o $$po $$po~ $(POT); \ + else \ + echo "Initializing $$po from $(POT)."; \ + msginit -i $(POT) -o $$po~ --locale=$*; \ + sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $$po~ > $$po; \ + fi \ + done + +pot: $(POT) + +# Extract message catalog from driconf.py. +$(POT): t_options.h + xgettext -L C --from-code utf-8 -o $(POT) t_options.h diff --git a/lib/mesa/src/util/xmlpool/Makefile.in b/lib/mesa/src/util/xmlpool/Makefile.in new file mode 100644 index 000000000..3bb8efbf1 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/Makefile.in @@ -0,0 +1,732 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Convenient makefile for managing translations. + +# Prerequisites: +# - GNU gettext +# - Python + +# Adding new translations +# ----------------------- + +# To start working on a new translation edit the POS=... line +# below. If you want to add for example a french translation, add +# fr.po. + +# Then run "make po" to generate a fresh .po file from translatable +# strings in t_options.h. Now you can edit the new .po file (fr.po in +# the example above) to translate the strings. Please make sure that +# your editor encodes the file in UTF-8. + +# Updating existing translations +# ------------------------------ + +# Run "make po" to update .po files with new translatable strings from +# t_options.h. Now you can edit the .po files you're interested +# in. Please make sure that your editor encodes the file in UTF-8. + +# Updating options.h +# ------------------ + +# Finally run "make" to generate options.h from t_options.h with all +# translations. Now you can rebuild the drivers. Any common options +# used by the drivers will have option descriptions with the latest +# translations. + +# Publishing translations +# ----------------------- + +# To get your translation(s) into Mesa CVS, please send me your +# <lang>.po file. + +# More information: +# - info gettext +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/util/xmlpool +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \ + $(top_srcdir)/m4/ax_check_gnu_make.m4 \ + $(top_srcdir)/m4/ax_check_python_mako_module.m4 \ + $(top_srcdir)/m4/ax_gcc_builtin.m4 \ + $(top_srcdir)/m4/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4/ax_prog_bison.m4 \ + $(top_srcdir)/m4/ax_prog_flex.m4 \ + $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/VERSION $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMDGPU_CFLAGS = @AMDGPU_CFLAGS@ +AMDGPU_LIBS = @AMDGPU_LIBS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +ANDROID_CFLAGS = @ANDROID_CFLAGS@ +ANDROID_LIBS = @ANDROID_LIBS@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BSYMBOLIC = @BSYMBOLIC@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CLANG_RESOURCE_DIR = @CLANG_RESOURCE_DIR@ +CLOCK_LIB = @CLOCK_LIB@ +CLOVER_STD_OVERRIDE = @CLOVER_STD_OVERRIDE@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +D3D_DRIVER_INSTALL_DIR = @D3D_DRIVER_INSTALL_DIR@ +DEFINES = @DEFINES@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DLOPEN_LIBS = @DLOPEN_LIBS@ +DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@ +DRI2PROTO_LIBS = @DRI2PROTO_LIBS@ +DRIGL_CFLAGS = @DRIGL_CFLAGS@ +DRIGL_LIBS = @DRIGL_LIBS@ +DRI_DRIVER_INSTALL_DIR = @DRI_DRIVER_INSTALL_DIR@ +DRI_DRIVER_SEARCH_DIR = @DRI_DRIVER_SEARCH_DIR@ +DRI_LIB_DEPS = @DRI_LIB_DEPS@ +DRI_PC_REQ_PRIV = @DRI_PC_REQ_PRIV@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGL_CFLAGS = @EGL_CFLAGS@ +EGL_LIB_DEPS = @EGL_LIB_DEPS@ +EGL_NATIVE_PLATFORM = @EGL_NATIVE_PLATFORM@ +EGREP = @EGREP@ +ETNAVIV_CFLAGS = @ETNAVIV_CFLAGS@ +ETNAVIV_LIBS = @ETNAVIV_LIBS@ +EXEEXT = @EXEEXT@ +EXPAT_CFLAGS = @EXPAT_CFLAGS@ +EXPAT_LIBS = @EXPAT_LIBS@ +FGREP = @FGREP@ +FREEDRENO_CFLAGS = @FREEDRENO_CFLAGS@ +FREEDRENO_LIBS = @FREEDRENO_LIBS@ +GALLIUM_PIPE_LOADER_DEFINES = @GALLIUM_PIPE_LOADER_DEFINES@ +GBM_PC_LIB_PRIV = @GBM_PC_LIB_PRIV@ +GBM_PC_REQ_PRIV = @GBM_PC_REQ_PRIV@ +GC_SECTIONS = @GC_SECTIONS@ +GLESv1_CM_LIB_DEPS = @GLESv1_CM_LIB_DEPS@ +GLESv1_CM_PC_LIB_PRIV = @GLESv1_CM_PC_LIB_PRIV@ +GLESv2_LIB_DEPS = @GLESv2_LIB_DEPS@ +GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@ +GLPROTO_CFLAGS = @GLPROTO_CFLAGS@ +GLPROTO_LIBS = @GLPROTO_LIBS@ +GLVND_CFLAGS = @GLVND_CFLAGS@ +GLVND_LIBS = @GLVND_LIBS@ +GLX_TLS = @GLX_TLS@ +GL_LIB = @GL_LIB@ +GL_LIB_DEPS = @GL_LIB_DEPS@ +GL_PC_CFLAGS = @GL_PC_CFLAGS@ +GL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@ +GL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@ +GREP = @GREP@ +HAVE_XF86VIDMODE = @HAVE_XF86VIDMODE@ +I915_CFLAGS = @I915_CFLAGS@ +I915_LIBS = @I915_LIBS@ +INDENT = @INDENT@ +INDENT_FLAGS = @INDENT_FLAGS@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LD_NO_UNDEFINED = @LD_NO_UNDEFINED@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBATOMIC_LIBS = @LIBATOMIC_LIBS@ +LIBCLC_INCLUDEDIR = @LIBCLC_INCLUDEDIR@ +LIBCLC_LIBEXECDIR = @LIBCLC_LIBEXECDIR@ +LIBDRM_CFLAGS = @LIBDRM_CFLAGS@ +LIBDRM_LIBS = @LIBDRM_LIBS@ +LIBELF_CFLAGS = @LIBELF_CFLAGS@ +LIBELF_LIBS = @LIBELF_LIBS@ +LIBGLVND_DATADIR = @LIBGLVND_DATADIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSENSORS_LIBS = @LIBSENSORS_LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIB_DIR = @LIB_DIR@ +LIB_EXT = @LIB_EXT@ +LIPO = @LIPO@ +LLVM_CFLAGS = @LLVM_CFLAGS@ +LLVM_CONFIG = @LLVM_CONFIG@ +LLVM_CXXFLAGS = @LLVM_CXXFLAGS@ +LLVM_INCLUDEDIR = @LLVM_INCLUDEDIR@ +LLVM_LDFLAGS = @LLVM_LDFLAGS@ +LLVM_LIBS = @LLVM_LIBS@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MSVC2013_COMPAT_CFLAGS = @MSVC2013_COMPAT_CFLAGS@ +MSVC2013_COMPAT_CXXFLAGS = @MSVC2013_COMPAT_CXXFLAGS@ +NINE_MAJOR = @NINE_MAJOR@ +NINE_MINOR = @NINE_MINOR@ +NINE_TINY = @NINE_TINY@ +NINE_VERSION = @NINE_VERSION@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NOUVEAU_CFLAGS = @NOUVEAU_CFLAGS@ +NOUVEAU_LIBS = @NOUVEAU_LIBS@ +NVVIEUX_CFLAGS = @NVVIEUX_CFLAGS@ +NVVIEUX_LIBS = @NVVIEUX_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OMX_BELLAGIO_CFLAGS = @OMX_BELLAGIO_CFLAGS@ +OMX_BELLAGIO_LIBS = @OMX_BELLAGIO_LIBS@ +OMX_BELLAGIO_LIB_INSTALL_DIR = @OMX_BELLAGIO_LIB_INSTALL_DIR@ +OPENCL_LIBNAME = @OPENCL_LIBNAME@ +OPENCL_VERSION = @OPENCL_VERSION@ +OSMESA_LIB = @OSMESA_LIB@ +OSMESA_LIB_DEPS = @OSMESA_LIB_DEPS@ +OSMESA_PC_LIB_PRIV = @OSMESA_PC_LIB_PRIV@ +OSMESA_PC_REQ = @OSMESA_PC_REQ@ +OSMESA_VERSION = @OSMESA_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POSIX_SHELL = @POSIX_SHELL@ +PTHREADSTUBS_CFLAGS = @PTHREADSTUBS_CFLAGS@ +PTHREADSTUBS_LIBS = @PTHREADSTUBS_LIBS@ +PTHREAD_CC = @PTHREAD_CC@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +PWR8_CFLAGS = @PWR8_CFLAGS@ +PYTHON2 = @PYTHON2@ +RADEON_CFLAGS = @RADEON_CFLAGS@ +RADEON_LIBS = @RADEON_LIBS@ +RANLIB = @RANLIB@ +RM = @RM@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIMPENROSE_CFLAGS = @SIMPENROSE_CFLAGS@ +SIMPENROSE_LIBS = @SIMPENROSE_LIBS@ +SSE41_CFLAGS = @SSE41_CFLAGS@ +STRIP = @STRIP@ +SWR_AVX2_CXXFLAGS = @SWR_AVX2_CXXFLAGS@ +SWR_AVX_CXXFLAGS = @SWR_AVX_CXXFLAGS@ +SWR_CXX11_CXXFLAGS = @SWR_CXX11_CXXFLAGS@ +SWR_KNL_CXXFLAGS = @SWR_KNL_CXXFLAGS@ +SWR_SKX_CXXFLAGS = @SWR_SKX_CXXFLAGS@ +VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ +VALGRIND_LIBS = @VALGRIND_LIBS@ +VA_CFLAGS = @VA_CFLAGS@ +VA_LIBS = @VA_LIBS@ +VA_LIB_INSTALL_DIR = @VA_LIB_INSTALL_DIR@ +VA_MAJOR = @VA_MAJOR@ +VA_MINOR = @VA_MINOR@ +VC5_SIMULATOR_CFLAGS = @VC5_SIMULATOR_CFLAGS@ +VC5_SIMULATOR_LIBS = @VC5_SIMULATOR_LIBS@ +VDPAU_CFLAGS = @VDPAU_CFLAGS@ +VDPAU_LIBS = @VDPAU_LIBS@ +VDPAU_LIB_INSTALL_DIR = @VDPAU_LIB_INSTALL_DIR@ +VDPAU_MAJOR = @VDPAU_MAJOR@ +VDPAU_MINOR = @VDPAU_MINOR@ +VERSION = @VERSION@ +VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@ +VISIBILITY_CXXFLAGS = @VISIBILITY_CXXFLAGS@ +VL_CFLAGS = @VL_CFLAGS@ +VL_LIBS = @VL_LIBS@ +VULKAN_ICD_INSTALL_DIR = @VULKAN_ICD_INSTALL_DIR@ +WAYLAND_CLIENT_CFLAGS = @WAYLAND_CLIENT_CFLAGS@ +WAYLAND_CLIENT_LIBS = @WAYLAND_CLIENT_LIBS@ +WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@ +WAYLAND_SCANNER = @WAYLAND_SCANNER@ +WAYLAND_SCANNER_CFLAGS = @WAYLAND_SCANNER_CFLAGS@ +WAYLAND_SCANNER_LIBS = @WAYLAND_SCANNER_LIBS@ +WAYLAND_SERVER_CFLAGS = @WAYLAND_SERVER_CFLAGS@ +WAYLAND_SERVER_LIBS = @WAYLAND_SERVER_LIBS@ +WNO_OVERRIDE_INIT = @WNO_OVERRIDE_INIT@ +X11_INCLUDES = @X11_INCLUDES@ +XA_MAJOR = @XA_MAJOR@ +XA_MINOR = @XA_MINOR@ +XA_TINY = @XA_TINY@ +XA_VERSION = @XA_VERSION@ +XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@ +XCB_DRI2_LIBS = @XCB_DRI2_LIBS@ +XCB_DRI3_CFLAGS = @XCB_DRI3_CFLAGS@ +XCB_DRI3_LIBS = @XCB_DRI3_LIBS@ +XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@ +XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@ +XLIBGL_CFLAGS = @XLIBGL_CFLAGS@ +XLIBGL_LIBS = @XLIBGL_LIBS@ +XVMC_CFLAGS = @XVMC_CFLAGS@ +XVMC_LIBS = @XVMC_LIBS@ +XVMC_LIB_INSTALL_DIR = @XVMC_LIB_INSTALL_DIR@ +XVMC_MAJOR = @XVMC_MAJOR@ +XVMC_MINOR = @XVMC_MINOR@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +acv_mako_found = @acv_mako_found@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +ax_pthread_config = @ax_pthread_config@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +ifGNUmake = @ifGNUmake@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# The set of supported languages. Add languages as needed. +POS = ca.po de.po es.po nl.po fr.po sv.po + +# +# Don't change anything below, unless you know what you're doing. +# +LANGS = $(POS:%.po=%) +MOS = $(POS:%.po=%/LC_MESSAGES/options.mo) +POT = xmlpool.pot +EXTRA_DIST = \ + gen_xmlpool.py \ + options.h \ + t_options.h \ + $(POS) \ + $(MOS) \ + SConscript + +BUILT_SOURCES = options.h +CLEANFILES = \ + options.h + + +# Default target options.h +LOCALEDIR := . +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/util/xmlpool/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/util/xmlpool/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check install install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +.PHONY: all clean pot po mo + $(POS) \ + $(MOS) +options.h: t_options.h $(MOS) + $(AM_V_GEN) $(PYTHON2) $(PYTHON_FLAGS) $(srcdir)/gen_xmlpool.py $(srcdir)/t_options.h $(LOCALEDIR) $(LANGS) > options.h + +# Update .mo files from the corresponding .po files. +%/LC_MESSAGES/options.mo: %.po + @mo="$@"; \ + lang=$${mo%%/*}; \ + echo "Updating ($$lang) $@ from $?."; \ + $(MKDIR_P) $$lang/LC_MESSAGES; \ + msgfmt -o $@ $? + +# Use this target to create or update .po files with new messages in +# driconf.py. +po: $(POT) + @for po in $(POS); do \ + if [ -f $$po ]; then \ + echo "Merging new strings from $(POT) into $@."; \ + mv $$po $$po~; \ + msgmerge -o $$po $$po~ $(POT); \ + else \ + echo "Initializing $$po from $(POT)."; \ + msginit -i $(POT) -o $$po~ --locale=$*; \ + sed -e 's/charset=.*\\n/charset=UTF-8\\n/' $$po~ > $$po; \ + fi \ + done + +pot: $(POT) + +# Extract message catalog from driconf.py. +$(POT): t_options.h + xgettext -L C --from-code utf-8 -o $(POT) t_options.h + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/mesa/src/util/xmlpool/SConscript b/lib/mesa/src/util/xmlpool/SConscript new file mode 100644 index 000000000..fa42554d3 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/SConscript @@ -0,0 +1,14 @@ +Import('*') + +from sys import executable as python_cmd + +LOCALEDIR = env.Dir('.').srcnode().abspath + +xmlpool_options, = env.CodeGenerate( + target = 'options.h', + script = 'gen_xmlpool.py', + source = ['t_options.h'], + command = python_cmd + ' $SCRIPT $SOURCE ' + LOCALEDIR + ' > $TARGET' +) + +Export('xmlpool_options') diff --git a/lib/mesa/src/util/xmlpool/ca.po b/lib/mesa/src/util/xmlpool/ca.po new file mode 100644 index 000000000..03bf29613 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/ca.po @@ -0,0 +1,348 @@ +# Language translations for Mesa package +# Traduccions al català del paquet «Mesa». +# +# Copyright © 2014 Alex Henrie <alexhenrie24@gmail.com> +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and 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. +msgid "" +msgstr "" +"Project-Id-Version: Mesa 10.1.0-devel\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-02-07 02:08-0700\n" +"PO-Revision-Date: 2015-02-23 14:28-0700\n" +"Last-Translator: Alex Henrie <alexhenrie24@gmail.com>\n" +"Language-Team: Catalan <ca@li.org>\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.7.4\n" + +#: t_options.h:56 +msgid "Debugging" +msgstr "Depuració" + +#: t_options.h:60 +msgid "Disable 3D acceleration" +msgstr "Deshabilita l'acceleració 3D" + +#: t_options.h:65 +msgid "Show performance boxes" +msgstr "Mostra les caixes de rendiment" + +#: t_options.h:70 +msgid "Enable flushing batchbuffer after each draw call" +msgstr "Habilita el buidatge del batchbuffer després de cada trucada de dibuix" + +#: t_options.h:75 +msgid "Enable flushing GPU caches with each draw call" +msgstr "" +"Habilita el buidatge de les memòries cau de GPU amb cada trucada de dibuix" + +#: t_options.h:80 +msgid "Disable throttling on first batch after flush" +msgstr "Deshabilita la regulació en el primer lot després de buidar" + +#: t_options.h:85 +msgid "Force GLSL extension default behavior to 'warn'" +msgstr "" +"Força que el comportament per defecte de les extensions GLSL sigui 'warn'" + +#: t_options.h:90 +msgid "Disable dual source blending" +msgstr "Deshabilita la barreja de font dual" + +#: t_options.h:95 +msgid "Disable backslash-based line continuations in GLSL source" +msgstr "" +"Deshabilita les continuacions de línia basades en barra invertida en la font " +"GLSL" + +#: t_options.h:100 +msgid "Disable GL_ARB_shader_bit_encoding" +msgstr "Deshabilita el GL_ARB_shader_bit_encoding" + +#: t_options.h:105 +msgid "" +"Force a default GLSL version for shaders that lack an explicit #version line" +msgstr "" +"Força una versió GLSL per defecte en els shaders als quals lis manca una " +"línia #version explícita" + +#: t_options.h:110 +msgid "Allow GLSL #extension directives in the middle of shaders" +msgstr "Permet les directives #extension GLSL en el mitjà dels shaders" + +#: t_options.h:120 +msgid "Image Quality" +msgstr "Qualitat d'imatge" + +#: t_options.h:133 +msgid "Texture color depth" +msgstr "Profunditat de color de textura" + +#: t_options.h:134 +msgid "Prefer frame buffer color depth" +msgstr "Prefereix profunditat de color del framebuffer" + +#: t_options.h:135 +msgid "Prefer 32 bits per texel" +msgstr "Prefereix 32 bits per texel" + +#: t_options.h:136 +msgid "Prefer 16 bits per texel" +msgstr "Prefereix 16 bits per texel" + +#: t_options.h:137 +msgid "Force 16 bits per texel" +msgstr "Força 16 bits per texel" + +#: t_options.h:143 +msgid "Initial maximum value for anisotropic texture filtering" +msgstr "Valor màxim inicial per a la filtració de textura anisòtropa" + +#: t_options.h:148 +msgid "Forbid negative texture LOD bias" +msgstr "" +"Prohibeix una parcialitat negativa del Nivell de Detalle (LOD) de les " +"textures" + +#: t_options.h:153 +msgid "" +"Enable S3TC texture compression even if software support is not available" +msgstr "" +"Habilita la compressió de textures S3TC encara que el suport de programari " +"no estigui disponible" + +#: t_options.h:160 +msgid "Initial color reduction method" +msgstr "Mètode inicial de reducció de color" + +#: t_options.h:161 +msgid "Round colors" +msgstr "Colors arrodonits" + +#: t_options.h:162 +msgid "Dither colors" +msgstr "Colors tramats" + +#: t_options.h:170 +msgid "Color rounding method" +msgstr "Mètode d'arrodoniment de color" + +#: t_options.h:171 +msgid "Round color components downward" +msgstr "Arrodoneix els components de color a baix" + +#: t_options.h:172 +msgid "Round to nearest color" +msgstr "Arrodoneix al color més proper" + +#: t_options.h:181 +msgid "Color dithering method" +msgstr "Mètode de tramat de color" + +#: t_options.h:182 +msgid "Horizontal error diffusion" +msgstr "Difusió d'error horitzontal" + +#: t_options.h:183 +msgid "Horizontal error diffusion, reset error at line start" +msgstr "Difusió d'error horitzontal, reinicia l'error a l'inici de la línia" + +#: t_options.h:184 +msgid "Ordered 2D color dithering" +msgstr "Tramat de color 2D ordenat" + +#: t_options.h:190 +msgid "Floating point depth buffer" +msgstr "Buffer de profunditat de punt flotant" + +#: t_options.h:195 +msgid "A post-processing filter to cel-shade the output" +msgstr "Un filtre de postprocessament per a aplicar cel shading a la sortida" + +#: t_options.h:200 +msgid "A post-processing filter to remove the red channel" +msgstr "Un filtre de postprocessament per a eliminar el canal vermell" + +#: t_options.h:205 +msgid "A post-processing filter to remove the green channel" +msgstr "Un filtre de postprocessament per a eliminar el canal verd" + +#: t_options.h:210 +msgid "A post-processing filter to remove the blue channel" +msgstr "Un filtre de postprocessament per a eliminar el canal blau" + +#: t_options.h:215 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality" +msgstr "" +"Antialiàsing morfològic basat en el MLAA de Jimenez. 0 per deshabilitar, 8 " +"per qualitat per defecte" + +#: t_options.h:220 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality. Color version, usable with 2d GL apps" +msgstr "" +"Antialiàsing morfològic basat en el MLAA de Jimenez. 0 per deshabilitar, 8 " +"per qualitat per defecte. Versió en color, utilitzable amb les aplicacions " +"GL 2D" + +#: t_options.h:230 +msgid "Performance" +msgstr "Rendiment" + +#: t_options.h:238 +msgid "TCL mode (Transformation, Clipping, Lighting)" +msgstr "Mode TCL (Transformació, Retall, Il·luminació)" + +#: t_options.h:239 +msgid "Use software TCL pipeline" +msgstr "Utilitza la canonada TCL de programari" + +#: t_options.h:240 +msgid "Use hardware TCL as first TCL pipeline stage" +msgstr "Utilitza el TCL de maquinari com a la primera fase de la canonada TCL" + +#: t_options.h:241 +msgid "Bypass the TCL pipeline" +msgstr "Passa per alt la canonada TCL" + +#: t_options.h:242 +msgid "" +"Bypass the TCL pipeline with state-based machine code generated on-the-fly" +msgstr "" +"Passa per alt la canonada TCL amb codi de màquina basat en estats, generat " +"sobre la marxa" + +#: t_options.h:251 +msgid "Method to limit rendering latency" +msgstr "Mètode per a limitar la latència de renderització" + +#: t_options.h:252 +msgid "Busy waiting for the graphics hardware" +msgstr "Espera activa pel maquinari de gràfics" + +#: t_options.h:253 +msgid "Sleep for brief intervals while waiting for the graphics hardware" +msgstr "Dorm per intervals breus mentre s'espera al maquinari de gràfics" + +#: t_options.h:254 +msgid "Let the graphics hardware emit a software interrupt and sleep" +msgstr "" +"Deixa que el maquinari de gràfics emeti una interrupció de programari i dormi" + +#: t_options.h:264 +msgid "Synchronization with vertical refresh (swap intervals)" +msgstr "Sincronització amb refresc vertical (intervals d'intercanvi)" + +#: t_options.h:265 +msgid "Never synchronize with vertical refresh, ignore application's choice" +msgstr "" +"Mai sincronitzis amb el refresc vertical, ignora l'elecció de l'aplicació" + +#: t_options.h:266 +msgid "Initial swap interval 0, obey application's choice" +msgstr "Interval d'intercanvi inicial 0, obeeix l'elecció de l'aplicació" + +#: t_options.h:267 +msgid "Initial swap interval 1, obey application's choice" +msgstr "Interval d'intercanvi inicial 1, obeeix l'elecció de l'aplicació" + +#: t_options.h:268 +msgid "" +"Always synchronize with vertical refresh, application chooses the minimum " +"swap interval" +msgstr "" +"Sempre sincronitza amb el refresc vertical, l'aplicació tria l'interval " +"mínim d'intercanvi" + +#: t_options.h:276 +msgid "Use HyperZ to boost performance" +msgstr "Utilitza el HyperZ per a augmentar el rendiment" + +#: t_options.h:281 +msgid "Number of texture units used" +msgstr "Nombre d'unitats de textura utilitzades" + +#: t_options.h:286 +msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" +msgstr "" +"Qualitat vs. velocitat de filtració de textura, àlies filtració \"brilinear" +"\" de textura" + +#: t_options.h:294 +msgid "Used types of texture memory" +msgstr "Tipus utilitzats de memòria de textura" + +#: t_options.h:295 +msgid "All available memory" +msgstr "Tota la memòria disponible" + +#: t_options.h:296 +msgid "Only card memory (if available)" +msgstr "Només memòria de targeta (si està disponible)" + +#: t_options.h:297 +msgid "Only GART (AGP/PCIE) memory (if available)" +msgstr "Només memòria GART (AGP/PCIE) (si està disponible)" + +#: t_options.h:309 +msgid "Features that are not hardware-accelerated" +msgstr "Característiques no accelerades per maquinari" + +#: t_options.h:313 +msgid "Enable extension GL_ARB_vertex_program" +msgstr "Habilita l'extensió GL_ARB_vertex_program" + +#: t_options.h:323 +msgid "Miscellaneous" +msgstr "Miscel·lània" + +#: t_options.h:327 +msgid "Create all visuals with a depth buffer" +msgstr "Crea tots els visuals amb buffer de profunditat" + +#: t_options.h:337 +msgid "Initialization" +msgstr "Inicialització" + +#: t_options.h:341 +msgid "Define the graphic device to use if possible" +msgstr "Defineix el dispositiu de gràfics que utilitzar si és possible" + +#: t_options.h:350 +msgid "Gallium Nine" +msgstr "Gallium Nine" + +#: t_options.h:354 +msgid "" +"Define the throttling value. -1 for no throttling, -2 for default (usually " +"2), 0 for glfinish behaviour" +msgstr "" +"Defineix el valor de regulació. -1 per a no regular, -2 per al predeterminat " +"(generalment 2), 0 per al comportament de glfinish" + +#: t_options.h:359 +msgid "Use an additional thread to submit buffers." +msgstr "Utilitza un fil addicional per a entregar els buffers." diff --git a/lib/mesa/src/util/xmlpool/ca/LC_MESSAGES/options.mo b/lib/mesa/src/util/xmlpool/ca/LC_MESSAGES/options.mo Binary files differnew file mode 100644 index 000000000..f2b0d5e16 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/ca/LC_MESSAGES/options.mo diff --git a/lib/mesa/src/util/xmlpool/de.po b/lib/mesa/src/util/xmlpool/de.po new file mode 100644 index 000000000..7b20d00a6 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/de.po @@ -0,0 +1,320 @@ +# German translations for DRI driver options. +# Copyright (C) 2005 Felix Kuehling +# This file is distributed under the same license as the Mesa package. +# Felix Kuehling <fxkuehl@gmx.de>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: Mesa 6.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-09-25 22:29-0600\n" +"PO-Revision-Date: 2005-04-11 01:34+0200\n" +"Last-Translator: Felix Kuehling <fxkuehl@gmx.de>\n" +"Language-Team: German <de@li.org>\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: t_options.h:56 +msgid "Debugging" +msgstr "Fehlersuche" + +#: t_options.h:60 +msgid "Disable 3D acceleration" +msgstr "3D-Beschleunigung abschalten" + +#: t_options.h:65 +msgid "Show performance boxes" +msgstr "Zeige Performanceboxen" + +#: t_options.h:70 +msgid "Enable flushing batchbuffer after each draw call" +msgstr "Aktiviere sofortige Leerung des Stapelpuffers nach jedem Zeichenaufruf" + +#: t_options.h:75 +msgid "Enable flushing GPU caches with each draw call" +msgstr "" +"Aktiviere sofortige Leerung der GPU-Zwischenspeicher mit jedem Zeichenaufruf" + +#: t_options.h:80 +msgid "Disable throttling on first batch after flush" +msgstr "" + +#: t_options.h:85 +msgid "Force GLSL extension default behavior to 'warn'" +msgstr "" + +#: t_options.h:90 +msgid "Disable dual source blending" +msgstr "" + +#: t_options.h:95 +msgid "Disable backslash-based line continuations in GLSL source" +msgstr "" + +#: t_options.h:100 +msgid "Disable GL_ARB_shader_bit_encoding" +msgstr "" + +#: t_options.h:105 +msgid "" +"Force a default GLSL version for shaders that lack an explicit #version line" +msgstr "" + +#: t_options.h:110 +msgid "Allow GLSL #extension directives in the middle of shaders" +msgstr "" + +#: t_options.h:120 +msgid "Image Quality" +msgstr "Bildqualität" + +#: t_options.h:133 +msgid "Texture color depth" +msgstr "Texturfarbtiefe" + +#: t_options.h:134 +msgid "Prefer frame buffer color depth" +msgstr "Bevorzuge Farbtiefe des Framebuffers" + +#: t_options.h:135 +msgid "Prefer 32 bits per texel" +msgstr "Bevorzuge 32 bits pro Texel" + +#: t_options.h:136 +msgid "Prefer 16 bits per texel" +msgstr "Bevorzuge 16 bits pro Texel" + +#: t_options.h:137 +msgid "Force 16 bits per texel" +msgstr "Erzwinge 16 bits pro Texel" + +#: t_options.h:143 +msgid "Initial maximum value for anisotropic texture filtering" +msgstr "Initialer Maximalwert für anisotropische Texturfilterung" + +#: t_options.h:148 +msgid "Forbid negative texture LOD bias" +msgstr "Verbiete negative Textur-Detailgradverschiebung" + +#: t_options.h:153 +msgid "" +"Enable S3TC texture compression even if software support is not available" +msgstr "" +"Aktiviere S3TC Texturkomprimierung auch wenn die nötige " +"Softwareunterstützung fehlt" + +#: t_options.h:160 +msgid "Initial color reduction method" +msgstr "Initiale Farbreduktionsmethode" + +#: t_options.h:161 +msgid "Round colors" +msgstr "Farben runden" + +#: t_options.h:162 +msgid "Dither colors" +msgstr "Farben rastern" + +#: t_options.h:170 +msgid "Color rounding method" +msgstr "Farbrundungsmethode" + +#: t_options.h:171 +msgid "Round color components downward" +msgstr "Farbkomponenten abrunden" + +#: t_options.h:172 +msgid "Round to nearest color" +msgstr "Zur ähnlichsten Farbe runden" + +#: t_options.h:181 +msgid "Color dithering method" +msgstr "Farbrasterungsmethode" + +#: t_options.h:182 +msgid "Horizontal error diffusion" +msgstr "Horizontale Fehlerstreuung" + +#: t_options.h:183 +msgid "Horizontal error diffusion, reset error at line start" +msgstr "Horizontale Fehlerstreuung, Fehler am Zeilenanfang zurücksetzen" + +#: t_options.h:184 +msgid "Ordered 2D color dithering" +msgstr "Geordnete 2D Farbrasterung" + +#: t_options.h:190 +msgid "Floating point depth buffer" +msgstr "Fließkomma z-Puffer" + +#: t_options.h:195 +msgid "A post-processing filter to cel-shade the output" +msgstr "Nachbearbeitungsfilter für Cell Shading" + +#: t_options.h:200 +msgid "A post-processing filter to remove the red channel" +msgstr "Nachbearbeitungsfilter zum Entfernen des Rotkanals" + +#: t_options.h:205 +msgid "A post-processing filter to remove the green channel" +msgstr "Nachbearbeitungsfilter zum Entfernen des Grünkanals" + +#: t_options.h:210 +msgid "A post-processing filter to remove the blue channel" +msgstr "Nachbearbeitungsfilter zum Entfernen des Blaukanals" + +#: t_options.h:215 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality" +msgstr "" +"Morphologische Kantenglättung (Anti-Aliasing) basierend auf Jimenez' MLAA. 0 " +"für deaktiviert, 8 für Standardqualität" + +#: t_options.h:220 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality. Color version, usable with 2d GL apps" +msgstr "" +"Morphologische Kantenglättung (Anti-Aliasing) basierend auf Jimenez' MLAA. 0 " +"für deaktiviert, 8 für Standardqualität. Farbversion, für 2D-Anwendungen" + +#: t_options.h:230 +msgid "Performance" +msgstr "Leistung" + +#: t_options.h:238 +msgid "TCL mode (Transformation, Clipping, Lighting)" +msgstr "TCL-Modus (Transformation, Clipping, Licht)" + +#: t_options.h:239 +msgid "Use software TCL pipeline" +msgstr "Benutze die Software-TCL-Pipeline" + +#: t_options.h:240 +msgid "Use hardware TCL as first TCL pipeline stage" +msgstr "Benutze Hardware TCL als erste Stufe der TCL-Pipeline" + +#: t_options.h:241 +msgid "Bypass the TCL pipeline" +msgstr "Umgehe die TCL-Pipeline" + +#: t_options.h:242 +msgid "" +"Bypass the TCL pipeline with state-based machine code generated on-the-fly" +msgstr "" +"Umgehe die TCL-Pipeline mit zur Laufzeit erzeugtem, zustandsbasiertem " +"Maschinencode" + +#: t_options.h:251 +msgid "Method to limit rendering latency" +msgstr "Methode zur Begrenzung der Bildverzögerung" + +#: t_options.h:252 +msgid "Busy waiting for the graphics hardware" +msgstr "Aktives Warten auf die Grafikhardware" + +#: t_options.h:253 +msgid "Sleep for brief intervals while waiting for the graphics hardware" +msgstr "Kurze Schlafintervalle beim Warten auf die Grafikhardware" + +#: t_options.h:254 +msgid "Let the graphics hardware emit a software interrupt and sleep" +msgstr "" +"Die Grafikhardware eine Softwareunterbrechnung erzeugen lassen und schlafen" + +#: t_options.h:264 +msgid "Synchronization with vertical refresh (swap intervals)" +msgstr "Synchronisation mit der vertikalen Bildwiederholung" + +#: t_options.h:265 +msgid "Never synchronize with vertical refresh, ignore application's choice" +msgstr "" +"Niemals mit der Bildwiederholung synchronisieren, Anweisungen der Anwendung " +"ignorieren" + +#: t_options.h:266 +msgid "Initial swap interval 0, obey application's choice" +msgstr "Initiales Bildinterval 0, Anweisungen der Anwendung gehorchen" + +#: t_options.h:267 +msgid "Initial swap interval 1, obey application's choice" +msgstr "Initiales Bildinterval 1, Anweisungen der Anwendung gehorchen" + +#: t_options.h:268 +msgid "" +"Always synchronize with vertical refresh, application chooses the minimum " +"swap interval" +msgstr "" +"Immer mit der Bildwiederholung synchronisieren, Anwendung wählt das minimale " +"Bildintervall" + +#: t_options.h:276 +msgid "Use HyperZ to boost performance" +msgstr "HyperZ zur Leistungssteigerung verwenden" + +#: t_options.h:281 +msgid "Number of texture units used" +msgstr "Anzahl der benutzten Textureinheiten" + +#: t_options.h:286 +msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" +msgstr "" +"Texturfilterqualität versus -geschwindigkeit, auch bekannt als „brilineare“ " +"Texturfilterung" + +#: t_options.h:294 +msgid "Used types of texture memory" +msgstr "Benutzte Arten von Texturspeicher" + +#: t_options.h:295 +msgid "All available memory" +msgstr "Aller verfügbarer Speicher" + +#: t_options.h:296 +msgid "Only card memory (if available)" +msgstr "Nur Grafikspeicher (falls verfügbar)" + +#: t_options.h:297 +msgid "Only GART (AGP/PCIE) memory (if available)" +msgstr "Nur GART-Speicher (AGP/PCIE) (falls verfügbar)" + +#: t_options.h:309 +msgid "Features that are not hardware-accelerated" +msgstr "Funktionalität, die nicht hardwarebeschleunigt ist" + +#: t_options.h:313 +msgid "Enable extension GL_ARB_vertex_program" +msgstr "Erweiterung GL_ARB_vertex_program aktivieren" + +#: t_options.h:323 +msgid "Miscellaneous" +msgstr "" + +#: t_options.h:327 +msgid "Create all visuals with a depth buffer" +msgstr "" + +#: t_options.h:337 +msgid "Initialization" +msgstr "" + +#: t_options.h:341 +msgid "Define the graphic device to use if possible" +msgstr "" + +#~ msgid "Support larger textures not guaranteed to fit into graphics memory" +#~ msgstr "" +#~ "Unterstütze grosse Texturen die evtl. nicht in den Grafikspeicher passen" + +#~ msgid "No" +#~ msgstr "Nein" + +#~ msgid "At least 1 texture must fit under worst-case assumptions" +#~ msgstr "Mindestens 1 Textur muss auch im schlechtesten Fall Platz haben" + +#~ msgid "Announce hardware limits" +#~ msgstr "Benutze Hardware-Limits" diff --git a/lib/mesa/src/util/xmlpool/de/LC_MESSAGES/options.mo b/lib/mesa/src/util/xmlpool/de/LC_MESSAGES/options.mo Binary files differnew file mode 100644 index 000000000..41c2b9bed --- /dev/null +++ b/lib/mesa/src/util/xmlpool/de/LC_MESSAGES/options.mo diff --git a/lib/mesa/src/util/xmlpool/es.po b/lib/mesa/src/util/xmlpool/es.po new file mode 100644 index 000000000..f9d950ac1 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/es.po @@ -0,0 +1,332 @@ +# translation of es.po to Spanish +# Spanish translations for PACKAGE package. +# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# David <deifo@ono.com>, 2005. +# David Rubio Miguélez <deifo@ono.com>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: es\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-02-07 02:08-0700\n" +"PO-Revision-Date: 2015-02-23 14:54-0700\n" +"Last-Translator: Alex Henrie <alexhenrie24@gmail.com>\n" +"Language-Team: Spanish <es@li.org>\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 1.7.4\n" + +#: t_options.h:56 +msgid "Debugging" +msgstr "Depuración" + +#: t_options.h:60 +msgid "Disable 3D acceleration" +msgstr "Deshabilitar aceleración 3D" + +#: t_options.h:65 +msgid "Show performance boxes" +msgstr "Mostrar cajas de rendimiento" + +#: t_options.h:70 +msgid "Enable flushing batchbuffer after each draw call" +msgstr "Habilitar vaciado del batchbuffer después de cada llamada de dibujo" + +#: t_options.h:75 +msgid "Enable flushing GPU caches with each draw call" +msgstr "Habilitar vaciado de los cachés GPU con cada llamada de dibujo" + +#: t_options.h:80 +msgid "Disable throttling on first batch after flush" +msgstr "Deshabilitar regulación del primer lote después de vaciar" + +#: t_options.h:85 +msgid "Force GLSL extension default behavior to 'warn'" +msgstr "" +"Forzar que el comportamiento por defecto de las extensiones GLSL sea 'warn'" + +#: t_options.h:90 +msgid "Disable dual source blending" +msgstr "Deshabilitar mezcla de fuente dual" + +#: t_options.h:95 +msgid "Disable backslash-based line continuations in GLSL source" +msgstr "" +"Deshabilitar continuaciones de línea basadas en barra inversa en el código " +"GLSL" + +#: t_options.h:100 +msgid "Disable GL_ARB_shader_bit_encoding" +msgstr "Deshabilitar GL_ARB_shader_bit_encoding" + +#: t_options.h:105 +msgid "" +"Force a default GLSL version for shaders that lack an explicit #version line" +msgstr "" +"Forzar una versión de GLSL por defecto en los shaders a los cuales les falta " +"una línea #version explícita" + +#: t_options.h:110 +msgid "Allow GLSL #extension directives in the middle of shaders" +msgstr "Permite directivas #extension GLSL en medio de los shaders" + +#: t_options.h:120 +msgid "Image Quality" +msgstr "Calidad de imagen" + +#: t_options.h:133 +msgid "Texture color depth" +msgstr "Profundidad de color de textura" + +#: t_options.h:134 +msgid "Prefer frame buffer color depth" +msgstr "Preferir profundidad de color del framebuffer" + +#: t_options.h:135 +msgid "Prefer 32 bits per texel" +msgstr "Preferir 32 bits por texel" + +#: t_options.h:136 +msgid "Prefer 16 bits per texel" +msgstr "Preferir 16 bits por texel" + +#: t_options.h:137 +msgid "Force 16 bits per texel" +msgstr "Forzar a 16 bits por texel" + +#: t_options.h:143 +msgid "Initial maximum value for anisotropic texture filtering" +msgstr "Valor máximo inicial para filtrado anisotrópico de textura" + +#: t_options.h:148 +msgid "Forbid negative texture LOD bias" +msgstr "Prohibir valores negativos de Nivel De Detalle (LOD) de texturas" + +#: t_options.h:153 +msgid "" +"Enable S3TC texture compression even if software support is not available" +msgstr "" +"Habilitar la compresión de texturas S3TC incluso si el soporte por software " +"no está disponible" + +#: t_options.h:160 +msgid "Initial color reduction method" +msgstr "Método inicial de reducción de color" + +#: t_options.h:161 +msgid "Round colors" +msgstr "Colores redondeados" + +#: t_options.h:162 +msgid "Dither colors" +msgstr "Colores suavizados" + +#: t_options.h:170 +msgid "Color rounding method" +msgstr "Método de redondeo de colores" + +#: t_options.h:171 +msgid "Round color components downward" +msgstr "Redondear hacia abajo los componentes de color" + +#: t_options.h:172 +msgid "Round to nearest color" +msgstr "Redondear al color más cercano" + +#: t_options.h:181 +msgid "Color dithering method" +msgstr "Método de suavizado de color" + +#: t_options.h:182 +msgid "Horizontal error diffusion" +msgstr "Difusión de error horizontal" + +#: t_options.h:183 +msgid "Horizontal error diffusion, reset error at line start" +msgstr "Difusión de error horizontal, reiniciar error al comienzo de línea" + +#: t_options.h:184 +msgid "Ordered 2D color dithering" +msgstr "Suavizado de color 2D ordenado" + +#: t_options.h:190 +msgid "Floating point depth buffer" +msgstr "Búfer de profundidad en coma flotante" + +#: t_options.h:195 +msgid "A post-processing filter to cel-shade the output" +msgstr "Un filtro de postprocesamiento para aplicar cel shading a la salida" + +#: t_options.h:200 +msgid "A post-processing filter to remove the red channel" +msgstr "Un filtro de postprocesamiento para eliminar el canal rojo" + +#: t_options.h:205 +msgid "A post-processing filter to remove the green channel" +msgstr "Un filtro de postprocesamiento para eliminar el canal verde" + +#: t_options.h:210 +msgid "A post-processing filter to remove the blue channel" +msgstr "Un filtro de postprocesamiento para eliminar el canal azul" + +#: t_options.h:215 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality" +msgstr "" +"Antialiasing morfológico basado en el MLAA de Jimenez. 0 para deshabilitar, " +"8 para calidad por defecto" + +#: t_options.h:220 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality. Color version, usable with 2d GL apps" +msgstr "" +"Antialiasing morfológico basado en el MLAA de Jimenez. 0 para deshabilitar, " +"8 para calidad por defecto. Versión en color, usable con aplicaciones GL 2D" + +#: t_options.h:230 +msgid "Performance" +msgstr "Rendimiento" + +#: t_options.h:238 +msgid "TCL mode (Transformation, Clipping, Lighting)" +msgstr "Modo TCL (Transformación, Recorte, Iluminación)" + +#: t_options.h:239 +msgid "Use software TCL pipeline" +msgstr "Usar tubería TCL por software" + +#: t_options.h:240 +msgid "Use hardware TCL as first TCL pipeline stage" +msgstr "Usar TCL por hardware en la primera fase de la tubería TCL" + +#: t_options.h:241 +msgid "Bypass the TCL pipeline" +msgstr "Pasar por alto la tubería TCL" + +#: t_options.h:242 +msgid "" +"Bypass the TCL pipeline with state-based machine code generated on-the-fly" +msgstr "" +"Pasar por alto la tubería TCL con código máquina basado en estados, generado " +"al vuelo" + +#: t_options.h:251 +msgid "Method to limit rendering latency" +msgstr "Método para limitar la latencia de renderización" + +#: t_options.h:252 +msgid "Busy waiting for the graphics hardware" +msgstr "Esperar activamente al hardware gráfico" + +#: t_options.h:253 +msgid "Sleep for brief intervals while waiting for the graphics hardware" +msgstr "Dormir en intervalos cortos mientras se espera al hardware gráfico" + +#: t_options.h:254 +msgid "Let the graphics hardware emit a software interrupt and sleep" +msgstr "" +"Permitir que el hardware gráfico emita una interrupción de software y duerma" + +#: t_options.h:264 +msgid "Synchronization with vertical refresh (swap intervals)" +msgstr "Sincronización con el refresco vertical (intervalos de intercambio)" + +#: t_options.h:265 +msgid "Never synchronize with vertical refresh, ignore application's choice" +msgstr "" +"No sincronizar nunca con el refresco vertical, ignorar la elección de la " +"aplicación" + +#: t_options.h:266 +msgid "Initial swap interval 0, obey application's choice" +msgstr "" +"Intervalo de intercambio inicial 0, obedecer la elección de la aplicación" + +#: t_options.h:267 +msgid "Initial swap interval 1, obey application's choice" +msgstr "" +"Intervalo de intercambio inicial 1, obedecer la elección de la aplicación" + +#: t_options.h:268 +msgid "" +"Always synchronize with vertical refresh, application chooses the minimum " +"swap interval" +msgstr "" +"Sincronizar siempre con el refresco vertical, la aplicación elige el " +"intervalo de intercambio mínimo" + +#: t_options.h:276 +msgid "Use HyperZ to boost performance" +msgstr "Usar HyperZ para potenciar rendimiento" + +#: t_options.h:281 +msgid "Number of texture units used" +msgstr "Número de unidades de textura usadas" + +#: t_options.h:286 +msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" +msgstr "" +"Calidad de filtrado de textura vs. velocidad, alias filtrado \"brilinear\" " +"de textura" + +#: t_options.h:294 +msgid "Used types of texture memory" +msgstr "Tipos de memoria de textura usados" + +#: t_options.h:295 +msgid "All available memory" +msgstr "Toda la memoria disponible" + +#: t_options.h:296 +msgid "Only card memory (if available)" +msgstr "Solo memoria de tarjeta (si está disponible)" + +#: t_options.h:297 +msgid "Only GART (AGP/PCIE) memory (if available)" +msgstr "Solo memoria GART (AGP/PCIE) (si está disponible)" + +#: t_options.h:309 +msgid "Features that are not hardware-accelerated" +msgstr "Características no aceleradas por hardware" + +#: t_options.h:313 +msgid "Enable extension GL_ARB_vertex_program" +msgstr "Habilitar la extensión GL_ARB_vertex_program" + +#: t_options.h:323 +msgid "Miscellaneous" +msgstr "Misceláneos" + +#: t_options.h:327 +msgid "Create all visuals with a depth buffer" +msgstr "Crear todos los visuales con búfer de profundidad" + +#: t_options.h:337 +msgid "Initialization" +msgstr "Inicialización" + +#: t_options.h:341 +msgid "Define the graphic device to use if possible" +msgstr "Define el dispositivo de gráficos que usar si es posible" + +#: t_options.h:350 +msgid "Gallium Nine" +msgstr "Gallium Nine" + +#: t_options.h:354 +msgid "" +"Define the throttling value. -1 for no throttling, -2 for default (usually " +"2), 0 for glfinish behaviour" +msgstr "" +"Define el valor de regulación. -1 para no regular, -2 para el por defecto " +"(generalmente 2), 0 para el comportamiento de glfinish" + +#: t_options.h:359 +msgid "Use an additional thread to submit buffers." +msgstr "Usar un hilo adicional para entregar los búfer." diff --git a/lib/mesa/src/util/xmlpool/es/LC_MESSAGES/options.mo b/lib/mesa/src/util/xmlpool/es/LC_MESSAGES/options.mo Binary files differnew file mode 100644 index 000000000..0145c680d --- /dev/null +++ b/lib/mesa/src/util/xmlpool/es/LC_MESSAGES/options.mo diff --git a/lib/mesa/src/util/xmlpool/fr.po b/lib/mesa/src/util/xmlpool/fr.po new file mode 100644 index 000000000..fa069652c --- /dev/null +++ b/lib/mesa/src/util/xmlpool/fr.po @@ -0,0 +1,310 @@ +# French translations for DRI driver options. +# Copyright (C) 2005 Stephane Marchesin +# This file is distributed under the same license as the Mesa package. +# Stephane Marchesin <marchesin@icps.u-strasbg.fr>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: Mesa 6.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-09-25 22:29-0600\n" +"PO-Revision-Date: 2005-04-11 01:34+0200\n" +"Last-Translator: Stephane Marchesin <marchesin@icps.u-strasbg.fr>\n" +"Language-Team: French <fr@li.org>\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: t_options.h:56 +msgid "Debugging" +msgstr "Debogage" + +#: t_options.h:60 +msgid "Disable 3D acceleration" +msgstr "Désactiver l'accélération 3D" + +#: t_options.h:65 +msgid "Show performance boxes" +msgstr "Afficher les boîtes de performance" + +#: t_options.h:70 +msgid "Enable flushing batchbuffer after each draw call" +msgstr "" + +#: t_options.h:75 +msgid "Enable flushing GPU caches with each draw call" +msgstr "" + +#: t_options.h:80 +msgid "Disable throttling on first batch after flush" +msgstr "" + +#: t_options.h:85 +msgid "Force GLSL extension default behavior to 'warn'" +msgstr "" + +#: t_options.h:90 +msgid "Disable dual source blending" +msgstr "" + +#: t_options.h:95 +msgid "Disable backslash-based line continuations in GLSL source" +msgstr "" + +#: t_options.h:100 +msgid "Disable GL_ARB_shader_bit_encoding" +msgstr "" + +#: t_options.h:105 +msgid "" +"Force a default GLSL version for shaders that lack an explicit #version line" +msgstr "" + +#: t_options.h:110 +msgid "Allow GLSL #extension directives in the middle of shaders" +msgstr "" + +#: t_options.h:120 +msgid "Image Quality" +msgstr "Qualité d'image" + +#: t_options.h:133 +msgid "Texture color depth" +msgstr "Profondeur de texture" + +#: t_options.h:134 +msgid "Prefer frame buffer color depth" +msgstr "Profondeur de couleur" + +#: t_options.h:135 +msgid "Prefer 32 bits per texel" +msgstr "Préférer 32 bits par texel" + +#: t_options.h:136 +msgid "Prefer 16 bits per texel" +msgstr "Prérérer 16 bits par texel" + +#: t_options.h:137 +msgid "Force 16 bits per texel" +msgstr "Forcer 16 bits par texel" + +#: t_options.h:143 +msgid "Initial maximum value for anisotropic texture filtering" +msgstr "Valeur maximale initiale pour le filtrage anisotropique de texture" + +#: t_options.h:148 +msgid "Forbid negative texture LOD bias" +msgstr "Interdire le LOD bias negatif" + +#: t_options.h:153 +msgid "" +"Enable S3TC texture compression even if software support is not available" +msgstr "" +"Activer la compression de texture S3TC même si le support logiciel est absent" + +#: t_options.h:160 +msgid "Initial color reduction method" +msgstr "Technique de réduction de couleurs" + +#: t_options.h:161 +msgid "Round colors" +msgstr "Arrondir les valeurs de couleur" + +#: t_options.h:162 +msgid "Dither colors" +msgstr "Tramer les couleurs" + +#: t_options.h:170 +msgid "Color rounding method" +msgstr "Méthode d'arrondi des couleurs" + +#: t_options.h:171 +msgid "Round color components downward" +msgstr "Arrondi à l'inférieur" + +#: t_options.h:172 +msgid "Round to nearest color" +msgstr "Arrondi au plus proche" + +#: t_options.h:181 +msgid "Color dithering method" +msgstr "Méthode de tramage" + +#: t_options.h:182 +msgid "Horizontal error diffusion" +msgstr "Diffusion d'erreur horizontale" + +#: t_options.h:183 +msgid "Horizontal error diffusion, reset error at line start" +msgstr "Diffusion d'erreur horizontale, réinitialisé pour chaque ligne" + +#: t_options.h:184 +msgid "Ordered 2D color dithering" +msgstr "Tramage ordonné des couleurs" + +#: t_options.h:190 +msgid "Floating point depth buffer" +msgstr "Z-buffer en virgule flottante" + +#: t_options.h:195 +msgid "A post-processing filter to cel-shade the output" +msgstr "" + +#: t_options.h:200 +msgid "A post-processing filter to remove the red channel" +msgstr "" + +#: t_options.h:205 +msgid "A post-processing filter to remove the green channel" +msgstr "" + +#: t_options.h:210 +msgid "A post-processing filter to remove the blue channel" +msgstr "" + +#: t_options.h:215 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality" +msgstr "" + +#: t_options.h:220 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality. Color version, usable with 2d GL apps" +msgstr "" + +#: t_options.h:230 +msgid "Performance" +msgstr "Performance" + +#: t_options.h:238 +msgid "TCL mode (Transformation, Clipping, Lighting)" +msgstr "Mode de TCL (Transformation, Clipping, Eclairage)" + +#: t_options.h:239 +msgid "Use software TCL pipeline" +msgstr "Utiliser un pipeline TCL logiciel" + +#: t_options.h:240 +msgid "Use hardware TCL as first TCL pipeline stage" +msgstr "Utiliser le TCL matériel pour le premier niveau de pipeline" + +#: t_options.h:241 +msgid "Bypass the TCL pipeline" +msgstr "Court-circuiter le pipeline TCL" + +#: t_options.h:242 +msgid "" +"Bypass the TCL pipeline with state-based machine code generated on-the-fly" +msgstr "" +"Court-circuiter le pipeline TCL par une machine à états qui génère le codede " +"TCL à la volée" + +#: t_options.h:251 +msgid "Method to limit rendering latency" +msgstr "Méthode d'attente de la carte graphique" + +#: t_options.h:252 +msgid "Busy waiting for the graphics hardware" +msgstr "Attente active de la carte graphique" + +#: t_options.h:253 +msgid "Sleep for brief intervals while waiting for the graphics hardware" +msgstr "Attente utilisant usleep()" + +#: t_options.h:254 +msgid "Let the graphics hardware emit a software interrupt and sleep" +msgstr "Utiliser les interruptions" + +#: t_options.h:264 +msgid "Synchronization with vertical refresh (swap intervals)" +msgstr "Synchronisation de l'affichage avec le balayage vertical" + +#: t_options.h:265 +msgid "Never synchronize with vertical refresh, ignore application's choice" +msgstr "" +"Ne jamais synchroniser avec le balayage vertical, ignorer le choix de " +"l'application" + +#: t_options.h:266 +msgid "Initial swap interval 0, obey application's choice" +msgstr "" +"Ne pas synchroniser avec le balayage vertical par défaut, mais obéir au " +"choix de l'application" + +#: t_options.h:267 +msgid "Initial swap interval 1, obey application's choice" +msgstr "" +"Synchroniser avec le balayage vertical par défaut, mais obéir au choix de " +"l'application" + +#: t_options.h:268 +msgid "" +"Always synchronize with vertical refresh, application chooses the minimum " +"swap interval" +msgstr "" +"Toujours synchroniser avec le balayage vertical, l'application choisit " +"l'intervalle minimal" + +#: t_options.h:276 +msgid "Use HyperZ to boost performance" +msgstr "Utiliser le HyperZ pour améliorer les performances" + +#: t_options.h:281 +msgid "Number of texture units used" +msgstr "Nombre d'unités de texture" + +#: t_options.h:286 +msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" +msgstr "" +"Qualité/performance du filtrage trilinéaire de texture (filtrage brilinéaire)" + +#: t_options.h:294 +msgid "Used types of texture memory" +msgstr "Types de mémoire de texture" + +#: t_options.h:295 +msgid "All available memory" +msgstr "Utiliser toute la mémoire disponible" + +#: t_options.h:296 +msgid "Only card memory (if available)" +msgstr "Utiliser uniquement la mémoire graphique (si disponible)" + +#: t_options.h:297 +msgid "Only GART (AGP/PCIE) memory (if available)" +msgstr "Utiliser uniquement la mémoire GART (AGP/PCIE) (si disponible)" + +#: t_options.h:309 +msgid "Features that are not hardware-accelerated" +msgstr "Fonctionnalités ne bénéficiant pas d'une accélération matérielle" + +#: t_options.h:313 +msgid "Enable extension GL_ARB_vertex_program" +msgstr "Activer l'extension GL_ARB_vertex_program" + +#: t_options.h:323 +msgid "Miscellaneous" +msgstr "" + +#: t_options.h:327 +msgid "Create all visuals with a depth buffer" +msgstr "" + +#: t_options.h:337 +msgid "Initialization" +msgstr "" + +#: t_options.h:341 +msgid "Define the graphic device to use if possible" +msgstr "" + +#~ msgid "" +#~ "Enable hack to allow larger textures with texture compression on radeon/" +#~ "r200" +#~ msgstr "" +#~ "Activer le hack permettant l'utilisation de textures de grande taille " +#~ "avec la compression de textures sur radeon/r200" diff --git a/lib/mesa/src/util/xmlpool/fr/LC_MESSAGES/options.mo b/lib/mesa/src/util/xmlpool/fr/LC_MESSAGES/options.mo Binary files differnew file mode 100644 index 000000000..af05db896 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/fr/LC_MESSAGES/options.mo diff --git a/lib/mesa/src/util/xmlpool/gen_xmlpool.py b/lib/mesa/src/util/xmlpool/gen_xmlpool.py new file mode 100644 index 000000000..eb68a6517 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/gen_xmlpool.py @@ -0,0 +1,203 @@ + +# +# Usage: +# gen_xmlpool.py /path/to/t_option.h localedir lang lang lang ... +# +# For each given language, this script expects to find a .mo file at +# `{localedir}/{language}/LC_MESSAGES/options.mo`. +# + +import sys +import gettext +import re + +# Path to t_options.h +template_header_path = sys.argv[1] + +localedir = sys.argv[2] + +# List of supported languages +languages = sys.argv[3:] + +# Escape special characters in C strings +def escapeCString (s): + escapeSeqs = {'\a' : '\\a', '\b' : '\\b', '\f' : '\\f', '\n' : '\\n', + '\r' : '\\r', '\t' : '\\t', '\v' : '\\v', '\\' : '\\\\'} + # " -> '' is a hack. Quotes (") aren't possible in XML attributes. + # Better use Unicode characters for typographic quotes in option + # descriptions and translations. + i = 0 + r = '' + while i < len(s): + # Special case: escape double quote with \u201c or \u201d, depending + # on whether it's an open or close quote. This is needed because plain + # double quotes are not possible in XML attributes. + if s[i] == '"': + if i == len(s)-1 or s[i+1].isspace(): + # close quote + q = u'\u201c' + else: + # open quote + q = u'\u201d' + r = r + q + elif escapeSeqs.has_key(s[i]): + r = r + escapeSeqs[s[i]] + else: + r = r + s[i] + i = i + 1 + return r + +# Expand escape sequences in C strings (needed for gettext lookup) +def expandCString (s): + escapeSeqs = {'a' : '\a', 'b' : '\b', 'f' : '\f', 'n' : '\n', + 'r' : '\r', 't' : '\t', 'v' : '\v', + '"' : '"', '\\' : '\\'} + i = 0 + escape = False + hexa = False + octa = False + num = 0 + digits = 0 + r = '' + while i < len(s): + if not escape: + if s[i] == '\\': + escape = True + else: + r = r + s[i] + elif hexa: + if (s[i] >= '0' and s[i] <= '9') or \ + (s[i] >= 'a' and s[i] <= 'f') or \ + (s[i] >= 'A' and s[i] <= 'F'): + num = num * 16 + int(s[i],16) + digits = digits + 1 + else: + digits = 2 + if digits >= 2: + hexa = False + escape = False + r = r + chr(num) + elif octa: + if s[i] >= '0' and s[i] <= '7': + num = num * 8 + int(s[i],8) + digits = digits + 1 + else: + digits = 3 + if digits >= 3: + octa = False + escape = False + r = r + chr(num) + else: + if escapeSeqs.has_key(s[i]): + r = r + escapeSeqs[s[i]] + escape = False + elif s[i] >= '0' and s[i] <= '7': + octa = True + num = int(s[i],8) + if num <= 3: + digits = 1 + else: + digits = 2 + elif s[i] == 'x' or s[i] == 'X': + hexa = True + num = 0 + digits = 0 + else: + r = r + s[i] + escape = False + i = i + 1 + return r + +# Expand matches. The first match is always a DESC or DESC_BEGIN match. +# Subsequent matches are ENUM matches. +# +# DESC, DESC_BEGIN format: \1 \2=<lang> \3 \4=gettext(" \5=<text> \6=") \7 +# ENUM format: \1 \2=gettext(" \3=<text> \4=") \5 +def expandMatches (matches, translations, end=None): + assert len(matches) > 0 + nTranslations = len(translations) + i = 0 + # Expand the description+enums for all translations + for lang,trans in translations: + i = i + 1 + # Make sure that all but the last line of a simple description + # are extended with a backslash. + suffix = '' + if len(matches) == 1 and i < len(translations) and \ + not matches[0].expand (r'\7').endswith('\\'): + suffix = ' \\' + # Expand the description line. Need to use ugettext in order to allow + # non-ascii unicode chars in the original English descriptions. + text = escapeCString (trans.ugettext (unicode (expandCString ( + matches[0].expand (r'\5')), "utf-8"))).encode("utf-8") + print matches[0].expand (r'\1' + lang + r'\3"' + text + r'"\7') + suffix + # Expand any subsequent enum lines + for match in matches[1:]: + text = escapeCString (trans.ugettext (unicode (expandCString ( + match.expand (r'\3')), "utf-8"))).encode("utf-8") + print match.expand (r'\1"' + text + r'"\5') + + # Expand description end + if end: + print end, + +# Compile a list of translation classes to all supported languages. +# The first translation is always a NullTranslations. +translations = [("en", gettext.NullTranslations())] +for lang in languages: + try: + trans = gettext.translation ("options", localedir, [lang]) + except IOError: + sys.stderr.write ("Warning: language '%s' not found.\n" % lang) + continue + translations.append ((lang, trans)) + +# Regular expressions: +reLibintl_h = re.compile (r'#\s*include\s*<libintl.h>') +reDESC = re.compile (r'(\s*DRI_CONF_DESC\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') +reDESC_BEGIN = re.compile (r'(\s*DRI_CONF_DESC_BEGIN\s*\(\s*)([a-z]+)(\s*,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') +reENUM = re.compile (r'(\s*DRI_CONF_ENUM\s*\([^,]+,\s*)(gettext\s*\(\s*")(.*)("\s*\))(\s*\)[ \t]*\\?)$') +reDESC_END = re.compile (r'\s*DRI_CONF_DESC_END') + +# Print a header +print \ +"/***********************************************************************\n" \ +" *** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! ***\n" \ +" ***********************************************************************/" + +# Process the options template and generate options.h with all +# translations. +template = file (template_header_path, "r") +descMatches = [] +for line in template: + if len(descMatches) > 0: + matchENUM = reENUM .match (line) + matchDESC_END = reDESC_END.match (line) + if matchENUM: + descMatches.append (matchENUM) + elif matchDESC_END: + expandMatches (descMatches, translations, line) + descMatches = [] + else: + sys.stderr.write ( + "Warning: unexpected line inside description dropped:\n%s\n" \ + % line) + continue + if reLibintl_h.search (line): + # Ignore (comment out) #include <libintl.h> + print "/* %s * commented out by gen_xmlpool.py */" % line + continue + matchDESC = reDESC .match (line) + matchDESC_BEGIN = reDESC_BEGIN.match (line) + if matchDESC: + assert len(descMatches) == 0 + expandMatches ([matchDESC], translations) + elif matchDESC_BEGIN: + assert len(descMatches) == 0 + descMatches = [matchDESC_BEGIN] + else: + print line, + +if len(descMatches) > 0: + sys.stderr.write ("Warning: unterminated description at end of file.\n") + expandMatches (descMatches, translations) diff --git a/lib/mesa/src/util/xmlpool/nl.po b/lib/mesa/src/util/xmlpool/nl.po new file mode 100644 index 000000000..86cb6e96d --- /dev/null +++ b/lib/mesa/src/util/xmlpool/nl.po @@ -0,0 +1,311 @@ +# Dutch translations for PACKAGE package. +# Copyright (C) 2005 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# <manfred.stienstra@dwerg.net>, 2005. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-09-25 22:29-0600\n" +"PO-Revision-Date: 2005-04-12 20:09+0200\n" +"Last-Translator: Manfred Stienstra <manfred.stienstra@dwerg.net>\n" +"Language-Team: Dutch <vertaling@nl.linux.org>\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: t_options.h:56 +msgid "Debugging" +msgstr "Debuggen" + +#: t_options.h:60 +msgid "Disable 3D acceleration" +msgstr "3D versnelling uitschakelen" + +#: t_options.h:65 +msgid "Show performance boxes" +msgstr "Laat prestatie boxjes zien" + +#: t_options.h:70 +msgid "Enable flushing batchbuffer after each draw call" +msgstr "" + +#: t_options.h:75 +msgid "Enable flushing GPU caches with each draw call" +msgstr "" + +#: t_options.h:80 +msgid "Disable throttling on first batch after flush" +msgstr "" + +#: t_options.h:85 +msgid "Force GLSL extension default behavior to 'warn'" +msgstr "" + +#: t_options.h:90 +msgid "Disable dual source blending" +msgstr "" + +#: t_options.h:95 +msgid "Disable backslash-based line continuations in GLSL source" +msgstr "" + +#: t_options.h:100 +msgid "Disable GL_ARB_shader_bit_encoding" +msgstr "" + +#: t_options.h:105 +msgid "" +"Force a default GLSL version for shaders that lack an explicit #version line" +msgstr "" + +#: t_options.h:110 +msgid "Allow GLSL #extension directives in the middle of shaders" +msgstr "" + +#: t_options.h:120 +msgid "Image Quality" +msgstr "Beeldkwaliteit" + +#: t_options.h:133 +msgid "Texture color depth" +msgstr "Textuurkleurendiepte" + +#: t_options.h:134 +msgid "Prefer frame buffer color depth" +msgstr "Prefereer kaderbufferkleurdiepte" + +#: t_options.h:135 +msgid "Prefer 32 bits per texel" +msgstr "Prefereer 32 bits per texel" + +#: t_options.h:136 +msgid "Prefer 16 bits per texel" +msgstr "Prefereer 16 bits per texel" + +#: t_options.h:137 +msgid "Force 16 bits per texel" +msgstr "Dwing 16 bits per texel af" + +#: t_options.h:143 +msgid "Initial maximum value for anisotropic texture filtering" +msgstr "Initïele maximum waarde voor anisotrophische textuur filtering" + +#: t_options.h:148 +msgid "Forbid negative texture LOD bias" +msgstr "Verbied negatief niveau detailonderscheid (LOD) van texturen" + +#: t_options.h:153 +msgid "" +"Enable S3TC texture compression even if software support is not available" +msgstr "" +"Schakel S3TC textuurcompressie in, zelfs als softwareondersteuning niet " +"aanwezig is" + +#: t_options.h:160 +msgid "Initial color reduction method" +msgstr "Initïele kleurreductie methode" + +#: t_options.h:161 +msgid "Round colors" +msgstr "Rond kleuren af" + +#: t_options.h:162 +msgid "Dither colors" +msgstr "Rasteriseer kleuren" + +#: t_options.h:170 +msgid "Color rounding method" +msgstr "Kleurafrondingmethode" + +#: t_options.h:171 +msgid "Round color components downward" +msgstr "Rond kleurencomponenten af naar beneden" + +#: t_options.h:172 +msgid "Round to nearest color" +msgstr "Rond af naar dichtsbijzijnde kleur" + +#: t_options.h:181 +msgid "Color dithering method" +msgstr "Kleurrasteriseringsmethode" + +#: t_options.h:182 +msgid "Horizontal error diffusion" +msgstr "Horizontale foutdiffusie" + +#: t_options.h:183 +msgid "Horizontal error diffusion, reset error at line start" +msgstr "Horizontale foutdiffusie, zet fout bij lijnbegin terug" + +#: t_options.h:184 +msgid "Ordered 2D color dithering" +msgstr "Geordende 2D kleurrasterisering" + +#: t_options.h:190 +msgid "Floating point depth buffer" +msgstr "Dieptebuffer als commagetal" + +#: t_options.h:195 +msgid "A post-processing filter to cel-shade the output" +msgstr "" + +#: t_options.h:200 +msgid "A post-processing filter to remove the red channel" +msgstr "" + +#: t_options.h:205 +msgid "A post-processing filter to remove the green channel" +msgstr "" + +#: t_options.h:210 +msgid "A post-processing filter to remove the blue channel" +msgstr "" + +#: t_options.h:215 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality" +msgstr "" + +#: t_options.h:220 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality. Color version, usable with 2d GL apps" +msgstr "" + +#: t_options.h:230 +msgid "Performance" +msgstr "Prestatie" + +#: t_options.h:238 +msgid "TCL mode (Transformation, Clipping, Lighting)" +msgstr "TCL-modus (Transformatie, Clipping, Licht)" + +#: t_options.h:239 +msgid "Use software TCL pipeline" +msgstr "Gebruik software TCL pijpleiding" + +#: t_options.h:240 +msgid "Use hardware TCL as first TCL pipeline stage" +msgstr "Gebruik hardware TCL as eerste TCL pijpleiding trap" + +#: t_options.h:241 +msgid "Bypass the TCL pipeline" +msgstr "Omzeil de TCL pijpleiding" + +#: t_options.h:242 +msgid "" +"Bypass the TCL pipeline with state-based machine code generated on-the-fly" +msgstr "" +"Omzeil de TCL pijpleiding met staatgebaseerde machinecode die tijdens " +"executie gegenereerd wordt" + +#: t_options.h:251 +msgid "Method to limit rendering latency" +msgstr "Methode om beeldopbouwvertraging te onderdrukken" + +#: t_options.h:252 +msgid "Busy waiting for the graphics hardware" +msgstr "Actief wachten voor de grafische hardware" + +#: t_options.h:253 +msgid "Sleep for brief intervals while waiting for the graphics hardware" +msgstr "" +"Slaap voor korte intervallen tijdens het wachten op de grafische hardware" + +#: t_options.h:254 +msgid "Let the graphics hardware emit a software interrupt and sleep" +msgstr "" +"Laat de grafische hardware een software onderbreking uitzenden en in slaap " +"vallen" + +#: t_options.h:264 +msgid "Synchronization with vertical refresh (swap intervals)" +msgstr "Synchronisatie met verticale verversing (interval omwisselen)" + +#: t_options.h:265 +msgid "Never synchronize with vertical refresh, ignore application's choice" +msgstr "" +"Nooit synchroniseren met verticale verversing, negeer de keuze van de " +"applicatie" + +#: t_options.h:266 +msgid "Initial swap interval 0, obey application's choice" +msgstr "Initïeel omwisselingsinterval 0, honoreer de keuze van de applicatie" + +#: t_options.h:267 +msgid "Initial swap interval 1, obey application's choice" +msgstr "Initïeel omwisselingsinterval 1, honoreer de keuze van de applicatie" + +#: t_options.h:268 +msgid "" +"Always synchronize with vertical refresh, application chooses the minimum " +"swap interval" +msgstr "" +"Synchroniseer altijd met verticale verversing, de applicatie kiest het " +"minimum omwisselingsinterval" + +#: t_options.h:276 +msgid "Use HyperZ to boost performance" +msgstr "Gebruik HyperZ om de prestaties te verbeteren" + +#: t_options.h:281 +msgid "Number of texture units used" +msgstr "Aantal textuureenheden in gebruik" + +#: t_options.h:286 +msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" +msgstr "" +"Textuurfilterkwaliteit versus -snelheid, ookwel bekend als “brilineaire” " +"textuurfiltering" + +#: t_options.h:294 +msgid "Used types of texture memory" +msgstr "Gebruikte soorten textuurgeheugen" + +#: t_options.h:295 +msgid "All available memory" +msgstr "Al het beschikbaar geheugen" + +#: t_options.h:296 +msgid "Only card memory (if available)" +msgstr "Alleen geheugen op de kaart (als het aanwezig is)" + +#: t_options.h:297 +msgid "Only GART (AGP/PCIE) memory (if available)" +msgstr "Alleen GART (AGP/PCIE) geheugen (als het aanwezig is)" + +#: t_options.h:309 +msgid "Features that are not hardware-accelerated" +msgstr "Eigenschappen die niet hardwareversneld zijn" + +#: t_options.h:313 +msgid "Enable extension GL_ARB_vertex_program" +msgstr "Zet uitbreiding GL_ARB_vertex_program aan" + +#: t_options.h:323 +msgid "Miscellaneous" +msgstr "" + +#: t_options.h:327 +msgid "Create all visuals with a depth buffer" +msgstr "" + +#: t_options.h:337 +msgid "Initialization" +msgstr "" + +#: t_options.h:341 +msgid "Define the graphic device to use if possible" +msgstr "" + +#~ msgid "" +#~ "Enable hack to allow larger textures with texture compression on radeon/" +#~ "r200" +#~ msgstr "" +#~ "Schakel hack in om met textuurcompressie grotere texturen toe te staan op " +#~ "een radeon/r200" diff --git a/lib/mesa/src/util/xmlpool/nl/LC_MESSAGES/options.mo b/lib/mesa/src/util/xmlpool/nl/LC_MESSAGES/options.mo Binary files differnew file mode 100644 index 000000000..7bf40f7bd --- /dev/null +++ b/lib/mesa/src/util/xmlpool/nl/LC_MESSAGES/options.mo diff --git a/lib/mesa/src/util/xmlpool/options.h b/lib/mesa/src/util/xmlpool/options.h new file mode 100644 index 000000000..ebf969d46 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/options.h @@ -0,0 +1,1028 @@ +/*********************************************************************** + *** THIS FILE IS GENERATED AUTOMATICALLY. DON'T EDIT! *** + ***********************************************************************/ +/* + * XML DRI client-side driver configuration + * Copyright (C) 2003 Felix Kuehling + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 + * FELIX KUEHLING, 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 t_options.h + * \brief Templates of common options + * \author Felix Kuehling + * + * This file defines macros for common options that can be used to + * construct driConfigOptions in the drivers. This file is only a + * template containing English descriptions for options wrapped in + * gettext(). xgettext can be used to extract translatable + * strings. These strings can then be translated by anyone familiar + * with GNU gettext. gen_xmlpool.py takes this template and fills in + * all the translations. The result (options.h) is included by + * xmlpool.h which in turn can be included by drivers. + * + * The macros used to describe otions in this file are defined in + * ../xmlpool.h. + */ + +/* This is needed for xgettext to extract translatable strings. + * gen_xmlpool.py will discard this line. */ +/* #include <libintl.h> + * commented out by gen_xmlpool.py */ + +/* + * predefined option sections and options with multi-lingual descriptions + */ + + +/** + * \brief Debugging options + */ +#define DRI_CONF_SECTION_DEBUG \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,"Debugging") \ + DRI_CONF_DESC(ca,"Depuració") \ + DRI_CONF_DESC(de,"Fehlersuche") \ + DRI_CONF_DESC(es,"Depuración") \ + DRI_CONF_DESC(nl,"Debuggen") \ + DRI_CONF_DESC(fr,"Debogage") \ + DRI_CONF_DESC(sv,"Felsökning") + +#define DRI_CONF_NO_RAST(def) \ +DRI_CONF_OPT_BEGIN_B(no_rast, def) \ + DRI_CONF_DESC(en,"Disable 3D acceleration") \ + DRI_CONF_DESC(ca,"Deshabilita l'acceleració 3D") \ + DRI_CONF_DESC(de,"3D-Beschleunigung abschalten") \ + DRI_CONF_DESC(es,"Deshabilitar aceleración 3D") \ + DRI_CONF_DESC(nl,"3D versnelling uitschakelen") \ + DRI_CONF_DESC(fr,"Désactiver l'accélération 3D") \ + DRI_CONF_DESC(sv,"Inaktivera 3D-accelerering") \ +DRI_CONF_OPT_END + +#define DRI_CONF_PERFORMANCE_BOXES(def) \ +DRI_CONF_OPT_BEGIN_B(performance_boxes, def) \ + DRI_CONF_DESC(en,"Show performance boxes") \ + DRI_CONF_DESC(ca,"Mostra les caixes de rendiment") \ + DRI_CONF_DESC(de,"Zeige Performanceboxen") \ + DRI_CONF_DESC(es,"Mostrar cajas de rendimiento") \ + DRI_CONF_DESC(nl,"Laat prestatie boxjes zien") \ + DRI_CONF_DESC(fr,"Afficher les boîtes de performance") \ + DRI_CONF_DESC(sv,"Visa prestandarutor") \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \ +DRI_CONF_OPT_BEGIN_B(always_flush_batch, def) \ + DRI_CONF_DESC(en,"Enable flushing batchbuffer after each draw call") \ + DRI_CONF_DESC(ca,"Habilita el buidatge del batchbuffer després de cada trucada de dibuix") \ + DRI_CONF_DESC(de,"Aktiviere sofortige Leerung des Stapelpuffers nach jedem Zeichenaufruf") \ + DRI_CONF_DESC(es,"Habilitar vaciado del batchbuffer después de cada llamada de dibujo") \ + DRI_CONF_DESC(nl,"Enable flushing batchbuffer after each draw call") \ + DRI_CONF_DESC(fr,"Enable flushing batchbuffer after each draw call") \ + DRI_CONF_DESC(sv,"Enable flushing batchbuffer after each draw call") \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALWAYS_FLUSH_CACHE(def) \ +DRI_CONF_OPT_BEGIN_B(always_flush_cache, def) \ + DRI_CONF_DESC(en,"Enable flushing GPU caches with each draw call") \ + DRI_CONF_DESC(ca,"Habilita el buidatge de les memòries cau de GPU amb cada trucada de dibuix") \ + DRI_CONF_DESC(de,"Aktiviere sofortige Leerung der GPU-Zwischenspeicher mit jedem Zeichenaufruf") \ + DRI_CONF_DESC(es,"Habilitar vaciado de los cachés GPU con cada llamada de dibujo") \ + DRI_CONF_DESC(nl,"Enable flushing GPU caches with each draw call") \ + DRI_CONF_DESC(fr,"Enable flushing GPU caches with each draw call") \ + DRI_CONF_DESC(sv,"Enable flushing GPU caches with each draw call") \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_THROTTLING(def) \ +DRI_CONF_OPT_BEGIN_B(disable_throttling, def) \ + DRI_CONF_DESC(en,"Disable throttling on first batch after flush") \ + DRI_CONF_DESC(ca,"Deshabilita la regulació en el primer lot després de buidar") \ + DRI_CONF_DESC(de,"Disable throttling on first batch after flush") \ + DRI_CONF_DESC(es,"Deshabilitar regulación del primer lote después de vaciar") \ + DRI_CONF_DESC(nl,"Disable throttling on first batch after flush") \ + DRI_CONF_DESC(fr,"Disable throttling on first batch after flush") \ + DRI_CONF_DESC(sv,"Disable throttling on first batch after flush") \ +DRI_CONF_OPT_END + +#define DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN(def) \ +DRI_CONF_OPT_BEGIN_B(force_glsl_extensions_warn, def) \ + DRI_CONF_DESC(en,"Force GLSL extension default behavior to 'warn'") \ + DRI_CONF_DESC(ca,"Força que el comportament per defecte de les extensions GLSL sigui 'warn'") \ + DRI_CONF_DESC(de,"Force GLSL extension default behavior to 'warn'") \ + DRI_CONF_DESC(es,"Forzar que el comportamiento por defecto de las extensiones GLSL sea 'warn'") \ + DRI_CONF_DESC(nl,"Force GLSL extension default behavior to 'warn'") \ + DRI_CONF_DESC(fr,"Force GLSL extension default behavior to 'warn'") \ + DRI_CONF_DESC(sv,"Force GLSL extension default behavior to 'warn'") \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED(def) \ +DRI_CONF_OPT_BEGIN_B(disable_blend_func_extended, def) \ + DRI_CONF_DESC(en,"Disable dual source blending") \ + DRI_CONF_DESC(ca,"Deshabilita la barreja de font dual") \ + DRI_CONF_DESC(de,"Disable dual source blending") \ + DRI_CONF_DESC(es,"Deshabilitar mezcla de fuente dual") \ + DRI_CONF_DESC(nl,"Disable dual source blending") \ + DRI_CONF_DESC(fr,"Disable dual source blending") \ + DRI_CONF_DESC(sv,"Disable dual source blending") \ +DRI_CONF_OPT_END + +#define DRI_CONF_DUAL_COLOR_BLEND_BY_LOCATION(def) \ +DRI_CONF_OPT_BEGIN_B(dual_color_blend_by_location, def) \ + DRI_CONF_DESC(en,"Identify dual color blending sources by location rather than index") \ + DRI_CONF_DESC(ca,"Identify dual color blending sources by location rather than index") \ + DRI_CONF_DESC(de,"Identify dual color blending sources by location rather than index") \ + DRI_CONF_DESC(es,"Identify dual color blending sources by location rather than index") \ + DRI_CONF_DESC(nl,"Identify dual color blending sources by location rather than index") \ + DRI_CONF_DESC(fr,"Identify dual color blending sources by location rather than index") \ + DRI_CONF_DESC(sv,"Identify dual color blending sources by location rather than index") \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS(def) \ +DRI_CONF_OPT_BEGIN_B(disable_glsl_line_continuations, def) \ + DRI_CONF_DESC(en,"Disable backslash-based line continuations in GLSL source") \ + DRI_CONF_DESC(ca,"Deshabilita les continuacions de línia basades en barra invertida en la font GLSL") \ + DRI_CONF_DESC(de,"Disable backslash-based line continuations in GLSL source") \ + DRI_CONF_DESC(es,"Deshabilitar continuaciones de línea basadas en barra inversa en el código GLSL") \ + DRI_CONF_DESC(nl,"Disable backslash-based line continuations in GLSL source") \ + DRI_CONF_DESC(fr,"Disable backslash-based line continuations in GLSL source") \ + DRI_CONF_DESC(sv,"Disable backslash-based line continuations in GLSL source") \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_SHADER_BIT_ENCODING(def) \ +DRI_CONF_OPT_BEGIN_B(disable_shader_bit_encoding, def) \ + DRI_CONF_DESC(en,"Disable GL_ARB_shader_bit_encoding") \ + DRI_CONF_DESC(ca,"Deshabilita el GL_ARB_shader_bit_encoding") \ + DRI_CONF_DESC(de,"Disable GL_ARB_shader_bit_encoding") \ + DRI_CONF_DESC(es,"Deshabilitar GL_ARB_shader_bit_encoding") \ + DRI_CONF_DESC(nl,"Disable GL_ARB_shader_bit_encoding") \ + DRI_CONF_DESC(fr,"Disable GL_ARB_shader_bit_encoding") \ + DRI_CONF_DESC(sv,"Disable GL_ARB_shader_bit_encoding") \ +DRI_CONF_OPT_END + +#define DRI_CONF_FORCE_GLSL_VERSION(def) \ +DRI_CONF_OPT_BEGIN_V(force_glsl_version, int, def, "0:999") \ + DRI_CONF_DESC(en,"Force a default GLSL version for shaders that lack an explicit #version line") \ + DRI_CONF_DESC(ca,"Força una versió GLSL per defecte en els shaders als quals lis manca una línia #version explícita") \ + DRI_CONF_DESC(de,"Force a default GLSL version for shaders that lack an explicit #version line") \ + DRI_CONF_DESC(es,"Forzar una versión de GLSL por defecto en los shaders a los cuales les falta una línea #version explícita") \ + DRI_CONF_DESC(nl,"Force a default GLSL version for shaders that lack an explicit #version line") \ + DRI_CONF_DESC(fr,"Force a default GLSL version for shaders that lack an explicit #version line") \ + DRI_CONF_DESC(sv,"Force a default GLSL version for shaders that lack an explicit #version line") \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALLOW_GLSL_EXTENSION_DIRECTIVE_MIDSHADER(def) \ +DRI_CONF_OPT_BEGIN_B(allow_glsl_extension_directive_midshader, def) \ + DRI_CONF_DESC(en,"Allow GLSL #extension directives in the middle of shaders") \ + DRI_CONF_DESC(ca,"Permet les directives #extension GLSL en el mitjà dels shaders") \ + DRI_CONF_DESC(de,"Allow GLSL #extension directives in the middle of shaders") \ + DRI_CONF_DESC(es,"Permite directivas #extension GLSL en medio de los shaders") \ + DRI_CONF_DESC(nl,"Allow GLSL #extension directives in the middle of shaders") \ + DRI_CONF_DESC(fr,"Allow GLSL #extension directives in the middle of shaders") \ + DRI_CONF_DESC(sv,"Allow GLSL #extension directives in the middle of shaders") \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALLOW_GLSL_BUILTIN_VARIABLE_REDECLARATION(def) \ +DRI_CONF_OPT_BEGIN_B(allow_glsl_builtin_variable_redeclaration, def) \ + DRI_CONF_DESC(en,"Allow GLSL built-in variables to be redeclared verbatim") \ + DRI_CONF_DESC(ca,"Allow GLSL built-in variables to be redeclared verbatim") \ + DRI_CONF_DESC(de,"Allow GLSL built-in variables to be redeclared verbatim") \ + DRI_CONF_DESC(es,"Allow GLSL built-in variables to be redeclared verbatim") \ + DRI_CONF_DESC(nl,"Allow GLSL built-in variables to be redeclared verbatim") \ + DRI_CONF_DESC(fr,"Allow GLSL built-in variables to be redeclared verbatim") \ + DRI_CONF_DESC(sv,"Allow GLSL built-in variables to be redeclared verbatim") \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALLOW_HIGHER_COMPAT_VERSION(def) \ +DRI_CONF_OPT_BEGIN_B(allow_higher_compat_version, def) \ + DRI_CONF_DESC(en,"Allow a higher compat profile (version 3.1+) for apps that request it") \ + DRI_CONF_DESC(ca,"Allow a higher compat profile (version 3.1+) for apps that request it") \ + DRI_CONF_DESC(de,"Allow a higher compat profile (version 3.1+) for apps that request it") \ + DRI_CONF_DESC(es,"Allow a higher compat profile (version 3.1+) for apps that request it") \ + DRI_CONF_DESC(nl,"Allow a higher compat profile (version 3.1+) for apps that request it") \ + DRI_CONF_DESC(fr,"Allow a higher compat profile (version 3.1+) for apps that request it") \ + DRI_CONF_DESC(sv,"Allow a higher compat profile (version 3.1+) for apps that request it") \ +DRI_CONF_OPT_END + +#define DRI_CONF_FORCE_GLSL_ABS_SQRT(def) \ +DRI_CONF_OPT_BEGIN_B(force_glsl_abs_sqrt, def) \ + DRI_CONF_DESC(en,"Force computing the absolute value for sqrt() and inversesqrt()") \ + DRI_CONF_DESC(ca,"Force computing the absolute value for sqrt() and inversesqrt()") \ + DRI_CONF_DESC(de,"Force computing the absolute value for sqrt() and inversesqrt()") \ + DRI_CONF_DESC(es,"Force computing the absolute value for sqrt() and inversesqrt()") \ + DRI_CONF_DESC(nl,"Force computing the absolute value for sqrt() and inversesqrt()") \ + DRI_CONF_DESC(fr,"Force computing the absolute value for sqrt() and inversesqrt()") \ + DRI_CONF_DESC(sv,"Force computing the absolute value for sqrt() and inversesqrt()") \ +DRI_CONF_OPT_END + +#define DRI_CONF_GLSL_CORRECT_DERIVATIVES_AFTER_DISCARD(def) \ +DRI_CONF_OPT_BEGIN_B(glsl_correct_derivatives_after_discard, def) \ + DRI_CONF_DESC(en,"Implicit and explicit derivatives after a discard behave as if the discard didn't happen") \ + DRI_CONF_DESC(ca,"Implicit and explicit derivatives after a discard behave as if the discard didn't happen") \ + DRI_CONF_DESC(de,"Implicit and explicit derivatives after a discard behave as if the discard didn't happen") \ + DRI_CONF_DESC(es,"Implicit and explicit derivatives after a discard behave as if the discard didn't happen") \ + DRI_CONF_DESC(nl,"Implicit and explicit derivatives after a discard behave as if the discard didn't happen") \ + DRI_CONF_DESC(fr,"Implicit and explicit derivatives after a discard behave as if the discard didn't happen") \ + DRI_CONF_DESC(sv,"Implicit and explicit derivatives after a discard behave as if the discard didn't happen") \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALLOW_GLSL_CROSS_STAGE_INTERPOLATION_MISMATCH(def) \ +DRI_CONF_OPT_BEGIN_B(allow_glsl_cross_stage_interpolation_mismatch, def) \ + DRI_CONF_DESC(en,"Allow interpolation qualifier mismatch across shader stages") \ + DRI_CONF_DESC(ca,"Allow interpolation qualifier mismatch across shader stages") \ + DRI_CONF_DESC(de,"Allow interpolation qualifier mismatch across shader stages") \ + DRI_CONF_DESC(es,"Allow interpolation qualifier mismatch across shader stages") \ + DRI_CONF_DESC(nl,"Allow interpolation qualifier mismatch across shader stages") \ + DRI_CONF_DESC(fr,"Allow interpolation qualifier mismatch across shader stages") \ + DRI_CONF_DESC(sv,"Allow interpolation qualifier mismatch across shader stages") \ +DRI_CONF_OPT_END + +/** + * \brief Image quality-related options + */ +#define DRI_CONF_SECTION_QUALITY \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,"Image Quality") \ + DRI_CONF_DESC(ca,"Qualitat d'imatge") \ + DRI_CONF_DESC(de,"Bildqualität") \ + DRI_CONF_DESC(es,"Calidad de imagen") \ + DRI_CONF_DESC(nl,"Beeldkwaliteit") \ + DRI_CONF_DESC(fr,"Qualité d'image") \ + DRI_CONF_DESC(sv,"Bildkvalitet") + +#define DRI_CONF_EXCESS_MIPMAP(def) \ +DRI_CONF_OPT_BEGIN_B(excess_mipmap, def) \ + DRI_CONF_DESC(en,"Enable extra mipmap level") \ +DRI_CONF_OPT_END + +#define DRI_CONF_TEXTURE_DEPTH_FB 0 +#define DRI_CONF_TEXTURE_DEPTH_32 1 +#define DRI_CONF_TEXTURE_DEPTH_16 2 +#define DRI_CONF_TEXTURE_DEPTH_FORCE_16 3 +#define DRI_CONF_TEXTURE_DEPTH(def) \ +DRI_CONF_OPT_BEGIN_V(texture_depth,enum,def,"0:3") \ + DRI_CONF_DESC_BEGIN(en,"Texture color depth") \ + DRI_CONF_ENUM(0,"Prefer frame buffer color depth") \ + DRI_CONF_ENUM(1,"Prefer 32 bits per texel") \ + DRI_CONF_ENUM(2,"Prefer 16 bits per texel") \ + DRI_CONF_ENUM(3,"Force 16 bits per texel") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(ca,"Profunditat de color de textura") \ + DRI_CONF_ENUM(0,"Prefereix profunditat de color del framebuffer") \ + DRI_CONF_ENUM(1,"Prefereix 32 bits per texel") \ + DRI_CONF_ENUM(2,"Prefereix 16 bits per texel") \ + DRI_CONF_ENUM(3,"Força 16 bits per texel") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(de,"Texturfarbtiefe") \ + DRI_CONF_ENUM(0,"Bevorzuge Farbtiefe des Framebuffers") \ + DRI_CONF_ENUM(1,"Bevorzuge 32 bits pro Texel") \ + DRI_CONF_ENUM(2,"Bevorzuge 16 bits pro Texel") \ + DRI_CONF_ENUM(3,"Erzwinge 16 bits pro Texel") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(es,"Profundidad de color de textura") \ + DRI_CONF_ENUM(0,"Preferir profundidad de color del framebuffer") \ + DRI_CONF_ENUM(1,"Preferir 32 bits por texel") \ + DRI_CONF_ENUM(2,"Preferir 16 bits por texel") \ + DRI_CONF_ENUM(3,"Forzar a 16 bits por texel") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(nl,"Textuurkleurendiepte") \ + DRI_CONF_ENUM(0,"Prefereer kaderbufferkleurdiepte") \ + DRI_CONF_ENUM(1,"Prefereer 32 bits per texel") \ + DRI_CONF_ENUM(2,"Prefereer 16 bits per texel") \ + DRI_CONF_ENUM(3,"Dwing 16 bits per texel af") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(fr,"Profondeur de texture") \ + DRI_CONF_ENUM(0,"Profondeur de couleur") \ + DRI_CONF_ENUM(1,"Préférer 32 bits par texel") \ + DRI_CONF_ENUM(2,"Prérérer 16 bits par texel") \ + DRI_CONF_ENUM(3,"Forcer 16 bits par texel") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(sv,"Färgdjup för texturer") \ + DRI_CONF_ENUM(0,"Föredra färgdjupet för framebuffer") \ + DRI_CONF_ENUM(1,"Föredra 32 bitar per texel") \ + DRI_CONF_ENUM(2,"Föredra 16 bitar per texel") \ + DRI_CONF_ENUM(3,"Tvinga 16 bitar per texel") \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_DEF_MAX_ANISOTROPY(def,range) \ +DRI_CONF_OPT_BEGIN_V(def_max_anisotropy,float,def,range) \ + DRI_CONF_DESC(en,"Initial maximum value for anisotropic texture filtering") \ + DRI_CONF_DESC(ca,"Valor màxim inicial per a la filtració de textura anisòtropa") \ + DRI_CONF_DESC(de,"Initialer Maximalwert für anisotropische Texturfilterung") \ + DRI_CONF_DESC(es,"Valor máximo inicial para filtrado anisotrópico de textura") \ + DRI_CONF_DESC(nl,"Initïele maximum waarde voor anisotrophische textuur filtering") \ + DRI_CONF_DESC(fr,"Valeur maximale initiale pour le filtrage anisotropique de texture") \ + DRI_CONF_DESC(sv,"Initialt maximalt värde för anisotropisk texturfiltrering") \ +DRI_CONF_OPT_END + +#define DRI_CONF_NO_NEG_LOD_BIAS(def) \ +DRI_CONF_OPT_BEGIN_B(no_neg_lod_bias, def) \ + DRI_CONF_DESC(en,"Forbid negative texture LOD bias") \ + DRI_CONF_DESC(ca,"Prohibeix una parcialitat negativa del Nivell de Detalle (LOD) de les textures") \ + DRI_CONF_DESC(de,"Verbiete negative Textur-Detailgradverschiebung") \ + DRI_CONF_DESC(es,"Prohibir valores negativos de Nivel De Detalle (LOD) de texturas") \ + DRI_CONF_DESC(nl,"Verbied negatief niveau detailonderscheid (LOD) van texturen") \ + DRI_CONF_DESC(fr,"Interdire le LOD bias negatif") \ + DRI_CONF_DESC(sv,"Förbjud negativ LOD-kompensation för texturer") \ +DRI_CONF_OPT_END + +#define DRI_CONF_PRECISE_TRIG(def) \ +DRI_CONF_OPT_BEGIN_B(precise_trig, def) \ + DRI_CONF_DESC(en,"Prefer accuracy over performance in trig functions") \ + DRI_CONF_DESC(ca,"Prefer accuracy over performance in trig functions") \ + DRI_CONF_DESC(de,"Prefer accuracy over performance in trig functions") \ + DRI_CONF_DESC(es,"Prefer accuracy over performance in trig functions") \ + DRI_CONF_DESC(nl,"Prefer accuracy over performance in trig functions") \ + DRI_CONF_DESC(fr,"Prefer accuracy over performance in trig functions") \ + DRI_CONF_DESC(sv,"Prefer accuracy over performance in trig functions") \ +DRI_CONF_OPT_END + +#define DRI_CONF_COLOR_REDUCTION_ROUND 0 +#define DRI_CONF_COLOR_REDUCTION_DITHER 1 +#define DRI_CONF_COLOR_REDUCTION(def) \ +DRI_CONF_OPT_BEGIN_V(color_reduction,enum,def,"0:1") \ + DRI_CONF_DESC_BEGIN(en,"Initial color reduction method") \ + DRI_CONF_ENUM(0,"Round colors") \ + DRI_CONF_ENUM(1,"Dither colors") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(ca,"Mètode inicial de reducció de color") \ + DRI_CONF_ENUM(0,"Colors arrodonits") \ + DRI_CONF_ENUM(1,"Colors tramats") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(de,"Initiale Farbreduktionsmethode") \ + DRI_CONF_ENUM(0,"Farben runden") \ + DRI_CONF_ENUM(1,"Farben rastern") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(es,"Método inicial de reducción de color") \ + DRI_CONF_ENUM(0,"Colores redondeados") \ + DRI_CONF_ENUM(1,"Colores suavizados") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(nl,"Initïele kleurreductie methode") \ + DRI_CONF_ENUM(0,"Rond kleuren af") \ + DRI_CONF_ENUM(1,"Rasteriseer kleuren") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(fr,"Technique de réduction de couleurs") \ + DRI_CONF_ENUM(0,"Arrondir les valeurs de couleur") \ + DRI_CONF_ENUM(1,"Tramer les couleurs") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(sv,"Initial färgminskningsmetod") \ + DRI_CONF_ENUM(0,"Avrunda färger") \ + DRI_CONF_ENUM(1,"Utjämna färger") \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_ROUND_TRUNC 0 +#define DRI_CONF_ROUND_ROUND 1 +#define DRI_CONF_ROUND_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(round_mode,enum,def,"0:1") \ + DRI_CONF_DESC_BEGIN(en,"Color rounding method") \ + DRI_CONF_ENUM(0,"Round color components downward") \ + DRI_CONF_ENUM(1,"Round to nearest color") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(ca,"Mètode d'arrodoniment de color") \ + DRI_CONF_ENUM(0,"Arrodoneix els components de color a baix") \ + DRI_CONF_ENUM(1,"Arrodoneix al color més proper") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(de,"Farbrundungsmethode") \ + DRI_CONF_ENUM(0,"Farbkomponenten abrunden") \ + DRI_CONF_ENUM(1,"Zur ähnlichsten Farbe runden") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(es,"Método de redondeo de colores") \ + DRI_CONF_ENUM(0,"Redondear hacia abajo los componentes de color") \ + DRI_CONF_ENUM(1,"Redondear al color más cercano") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(nl,"Kleurafrondingmethode") \ + DRI_CONF_ENUM(0,"Rond kleurencomponenten af naar beneden") \ + DRI_CONF_ENUM(1,"Rond af naar dichtsbijzijnde kleur") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(fr,"Méthode d'arrondi des couleurs") \ + DRI_CONF_ENUM(0,"Arrondi à l'inférieur") \ + DRI_CONF_ENUM(1,"Arrondi au plus proche") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(sv,"Färgavrundningsmetod") \ + DRI_CONF_ENUM(0,"Avrunda färdkomponenter nedåt") \ + DRI_CONF_ENUM(1,"Avrunda till närmsta färg") \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_DITHER_XERRORDIFF 0 +#define DRI_CONF_DITHER_XERRORDIFFRESET 1 +#define DRI_CONF_DITHER_ORDERED 2 +#define DRI_CONF_DITHER_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(dither_mode,enum,def,"0:2") \ + DRI_CONF_DESC_BEGIN(en,"Color dithering method") \ + DRI_CONF_ENUM(0,"Horizontal error diffusion") \ + DRI_CONF_ENUM(1,"Horizontal error diffusion, reset error at line start") \ + DRI_CONF_ENUM(2,"Ordered 2D color dithering") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(ca,"Mètode de tramat de color") \ + DRI_CONF_ENUM(0,"Difusió d'error horitzontal") \ + DRI_CONF_ENUM(1,"Difusió d'error horitzontal, reinicia l'error a l'inici de la línia") \ + DRI_CONF_ENUM(2,"Tramat de color 2D ordenat") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(de,"Farbrasterungsmethode") \ + DRI_CONF_ENUM(0,"Horizontale Fehlerstreuung") \ + DRI_CONF_ENUM(1,"Horizontale Fehlerstreuung, Fehler am Zeilenanfang zurücksetzen") \ + DRI_CONF_ENUM(2,"Geordnete 2D Farbrasterung") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(es,"Método de suavizado de color") \ + DRI_CONF_ENUM(0,"Difusión de error horizontal") \ + DRI_CONF_ENUM(1,"Difusión de error horizontal, reiniciar error al comienzo de línea") \ + DRI_CONF_ENUM(2,"Suavizado de color 2D ordenado") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(nl,"Kleurrasteriseringsmethode") \ + DRI_CONF_ENUM(0,"Horizontale foutdiffusie") \ + DRI_CONF_ENUM(1,"Horizontale foutdiffusie, zet fout bij lijnbegin terug") \ + DRI_CONF_ENUM(2,"Geordende 2D kleurrasterisering") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(fr,"Méthode de tramage") \ + DRI_CONF_ENUM(0,"Diffusion d'erreur horizontale") \ + DRI_CONF_ENUM(1,"Diffusion d'erreur horizontale, réinitialisé pour chaque ligne") \ + DRI_CONF_ENUM(2,"Tramage ordonné des couleurs") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(sv,"Färgutjämningsmetod") \ + DRI_CONF_ENUM(0,"Horisontell felspridning") \ + DRI_CONF_ENUM(1,"Horisontell felspridning, återställ fel vid radbörjan") \ + DRI_CONF_ENUM(2,"Ordnad 2D-färgutjämning") \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_FLOAT_DEPTH(def) \ +DRI_CONF_OPT_BEGIN_B(float_depth, def) \ + DRI_CONF_DESC(en,"Floating point depth buffer") \ + DRI_CONF_DESC(ca,"Buffer de profunditat de punt flotant") \ + DRI_CONF_DESC(de,"Fließkomma z-Puffer") \ + DRI_CONF_DESC(es,"Búfer de profundidad en coma flotante") \ + DRI_CONF_DESC(nl,"Dieptebuffer als commagetal") \ + DRI_CONF_DESC(fr,"Z-buffer en virgule flottante") \ + DRI_CONF_DESC(sv,"Buffert för flytande punktdjup") \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_CELSHADE(def) \ +DRI_CONF_OPT_BEGIN_V(pp_celshade,enum,def,"0:1") \ + DRI_CONF_DESC(en,"A post-processing filter to cel-shade the output") \ + DRI_CONF_DESC(ca,"Un filtre de postprocessament per a aplicar cel shading a la sortida") \ + DRI_CONF_DESC(de,"Nachbearbeitungsfilter für Cell Shading") \ + DRI_CONF_DESC(es,"Un filtro de postprocesamiento para aplicar cel shading a la salida") \ + DRI_CONF_DESC(nl,"A post-processing filter to cel-shade the output") \ + DRI_CONF_DESC(fr,"A post-processing filter to cel-shade the output") \ + DRI_CONF_DESC(sv,"A post-processing filter to cel-shade the output") \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_NORED(def) \ +DRI_CONF_OPT_BEGIN_V(pp_nored,enum,def,"0:1") \ + DRI_CONF_DESC(en,"A post-processing filter to remove the red channel") \ + DRI_CONF_DESC(ca,"Un filtre de postprocessament per a eliminar el canal vermell") \ + DRI_CONF_DESC(de,"Nachbearbeitungsfilter zum Entfernen des Rotkanals") \ + DRI_CONF_DESC(es,"Un filtro de postprocesamiento para eliminar el canal rojo") \ + DRI_CONF_DESC(nl,"A post-processing filter to remove the red channel") \ + DRI_CONF_DESC(fr,"A post-processing filter to remove the red channel") \ + DRI_CONF_DESC(sv,"A post-processing filter to remove the red channel") \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_NOGREEN(def) \ +DRI_CONF_OPT_BEGIN_V(pp_nogreen,enum,def,"0:1") \ + DRI_CONF_DESC(en,"A post-processing filter to remove the green channel") \ + DRI_CONF_DESC(ca,"Un filtre de postprocessament per a eliminar el canal verd") \ + DRI_CONF_DESC(de,"Nachbearbeitungsfilter zum Entfernen des Grünkanals") \ + DRI_CONF_DESC(es,"Un filtro de postprocesamiento para eliminar el canal verde") \ + DRI_CONF_DESC(nl,"A post-processing filter to remove the green channel") \ + DRI_CONF_DESC(fr,"A post-processing filter to remove the green channel") \ + DRI_CONF_DESC(sv,"A post-processing filter to remove the green channel") \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_NOBLUE(def) \ +DRI_CONF_OPT_BEGIN_V(pp_noblue,enum,def,"0:1") \ + DRI_CONF_DESC(en,"A post-processing filter to remove the blue channel") \ + DRI_CONF_DESC(ca,"Un filtre de postprocessament per a eliminar el canal blau") \ + DRI_CONF_DESC(de,"Nachbearbeitungsfilter zum Entfernen des Blaukanals") \ + DRI_CONF_DESC(es,"Un filtro de postprocesamiento para eliminar el canal azul") \ + DRI_CONF_DESC(nl,"A post-processing filter to remove the blue channel") \ + DRI_CONF_DESC(fr,"A post-processing filter to remove the blue channel") \ + DRI_CONF_DESC(sv,"A post-processing filter to remove the blue channel") \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_JIMENEZMLAA(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(pp_jimenezmlaa,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality") \ + DRI_CONF_DESC(ca,"Antialiàsing morfològic basat en el MLAA de Jimenez. 0 per deshabilitar, 8 per qualitat per defecte") \ + DRI_CONF_DESC(de,"Morphologische Kantenglättung (Anti-Aliasing) basierend auf Jimenez' MLAA. 0 für deaktiviert, 8 für Standardqualität") \ + DRI_CONF_DESC(es,"Antialiasing morfológico basado en el MLAA de Jimenez. 0 para deshabilitar, 8 para calidad por defecto") \ + DRI_CONF_DESC(nl,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality") \ + DRI_CONF_DESC(fr,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality") \ + DRI_CONF_DESC(sv,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality") \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_JIMENEZMLAA_COLOR(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(pp_jimenezmlaa_color,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality. Color version, usable with 2d GL apps") \ + DRI_CONF_DESC(ca,"Antialiàsing morfològic basat en el MLAA de Jimenez. 0 per deshabilitar, 8 per qualitat per defecte. Versió en color, utilitzable amb les aplicacions GL 2D") \ + DRI_CONF_DESC(de,"Morphologische Kantenglättung (Anti-Aliasing) basierend auf Jimenez' MLAA. 0 für deaktiviert, 8 für Standardqualität. Farbversion, für 2D-Anwendungen") \ + DRI_CONF_DESC(es,"Antialiasing morfológico basado en el MLAA de Jimenez. 0 para deshabilitar, 8 para calidad por defecto. Versión en color, usable con aplicaciones GL 2D") \ + DRI_CONF_DESC(nl,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality. Color version, usable with 2d GL apps") \ + DRI_CONF_DESC(fr,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality. Color version, usable with 2d GL apps") \ + DRI_CONF_DESC(sv,"Morphological anti-aliasing based on Jimenez\' MLAA. 0 to disable, 8 for default quality. Color version, usable with 2d GL apps") \ +DRI_CONF_OPT_END + + + +/** + * \brief Performance-related options + */ +#define DRI_CONF_SECTION_PERFORMANCE \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,"Performance") \ + DRI_CONF_DESC(ca,"Rendiment") \ + DRI_CONF_DESC(de,"Leistung") \ + DRI_CONF_DESC(es,"Rendimiento") \ + DRI_CONF_DESC(nl,"Prestatie") \ + DRI_CONF_DESC(fr,"Performance") \ + DRI_CONF_DESC(sv,"Prestanda") + +#define DRI_CONF_TCL_SW 0 +#define DRI_CONF_TCL_PIPELINED 1 +#define DRI_CONF_TCL_VTXFMT 2 +#define DRI_CONF_TCL_CODEGEN 3 +#define DRI_CONF_TCL_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(tcl_mode,enum,def,"0:3") \ + DRI_CONF_DESC_BEGIN(en,"TCL mode (Transformation, Clipping, Lighting)") \ + DRI_CONF_ENUM(0,"Use software TCL pipeline") \ + DRI_CONF_ENUM(1,"Use hardware TCL as first TCL pipeline stage") \ + DRI_CONF_ENUM(2,"Bypass the TCL pipeline") \ + DRI_CONF_ENUM(3,"Bypass the TCL pipeline with state-based machine code generated on-the-fly") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(ca,"Mode TCL (Transformació, Retall, Il·luminació)") \ + DRI_CONF_ENUM(0,"Utilitza la canonada TCL de programari") \ + DRI_CONF_ENUM(1,"Utilitza el TCL de maquinari com a la primera fase de la canonada TCL") \ + DRI_CONF_ENUM(2,"Passa per alt la canonada TCL") \ + DRI_CONF_ENUM(3,"Passa per alt la canonada TCL amb codi de màquina basat en estats, generat sobre la marxa") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(de,"TCL-Modus (Transformation, Clipping, Licht)") \ + DRI_CONF_ENUM(0,"Benutze die Software-TCL-Pipeline") \ + DRI_CONF_ENUM(1,"Benutze Hardware TCL als erste Stufe der TCL-Pipeline") \ + DRI_CONF_ENUM(2,"Umgehe die TCL-Pipeline") \ + DRI_CONF_ENUM(3,"Umgehe die TCL-Pipeline mit zur Laufzeit erzeugtem, zustandsbasiertem Maschinencode") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(es,"Modo TCL (Transformación, Recorte, Iluminación)") \ + DRI_CONF_ENUM(0,"Usar tubería TCL por software") \ + DRI_CONF_ENUM(1,"Usar TCL por hardware en la primera fase de la tubería TCL") \ + DRI_CONF_ENUM(2,"Pasar por alto la tubería TCL") \ + DRI_CONF_ENUM(3,"Pasar por alto la tubería TCL con código máquina basado en estados, generado al vuelo") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(nl,"TCL-modus (Transformatie, Clipping, Licht)") \ + DRI_CONF_ENUM(0,"Gebruik software TCL pijpleiding") \ + DRI_CONF_ENUM(1,"Gebruik hardware TCL as eerste TCL pijpleiding trap") \ + DRI_CONF_ENUM(2,"Omzeil de TCL pijpleiding") \ + DRI_CONF_ENUM(3,"Omzeil de TCL pijpleiding met staatgebaseerde machinecode die tijdens executie gegenereerd wordt") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(fr,"Mode de TCL (Transformation, Clipping, Eclairage)") \ + DRI_CONF_ENUM(0,"Utiliser un pipeline TCL logiciel") \ + DRI_CONF_ENUM(1,"Utiliser le TCL matériel pour le premier niveau de pipeline") \ + DRI_CONF_ENUM(2,"Court-circuiter le pipeline TCL") \ + DRI_CONF_ENUM(3,"Court-circuiter le pipeline TCL par une machine à états qui génère le codede TCL à la volée") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(sv,"TCL-läge (Transformation, Clipping, Lighting)") \ + DRI_CONF_ENUM(0,"Använd programvaru-TCL-rörledning") \ + DRI_CONF_ENUM(1,"Använd maskinvaru-TCL som första TCL-rörledningssteg") \ + DRI_CONF_ENUM(2,"Kringgå TCL-rörledningen") \ + DRI_CONF_ENUM(3,"Kringgå TCL-rörledningen med tillståndsbaserad maskinkod som direktgenereras") \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_FTHROTTLE_BUSY 0 +#define DRI_CONF_FTHROTTLE_USLEEPS 1 +#define DRI_CONF_FTHROTTLE_IRQS 2 +#define DRI_CONF_FTHROTTLE_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(fthrottle_mode,enum,def,"0:2") \ + DRI_CONF_DESC_BEGIN(en,"Method to limit rendering latency") \ + DRI_CONF_ENUM(0,"Busy waiting for the graphics hardware") \ + DRI_CONF_ENUM(1,"Sleep for brief intervals while waiting for the graphics hardware") \ + DRI_CONF_ENUM(2,"Let the graphics hardware emit a software interrupt and sleep") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(ca,"Mètode per a limitar la latència de renderització") \ + DRI_CONF_ENUM(0,"Espera activa pel maquinari de gràfics") \ + DRI_CONF_ENUM(1,"Dorm per intervals breus mentre s'espera al maquinari de gràfics") \ + DRI_CONF_ENUM(2,"Deixa que el maquinari de gràfics emeti una interrupció de programari i dormi") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(de,"Methode zur Begrenzung der Bildverzögerung") \ + DRI_CONF_ENUM(0,"Aktives Warten auf die Grafikhardware") \ + DRI_CONF_ENUM(1,"Kurze Schlafintervalle beim Warten auf die Grafikhardware") \ + DRI_CONF_ENUM(2,"Die Grafikhardware eine Softwareunterbrechnung erzeugen lassen und schlafen") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(es,"Método para limitar la latencia de renderización") \ + DRI_CONF_ENUM(0,"Esperar activamente al hardware gráfico") \ + DRI_CONF_ENUM(1,"Dormir en intervalos cortos mientras se espera al hardware gráfico") \ + DRI_CONF_ENUM(2,"Permitir que el hardware gráfico emita una interrupción de software y duerma") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(nl,"Methode om beeldopbouwvertraging te onderdrukken") \ + DRI_CONF_ENUM(0,"Actief wachten voor de grafische hardware") \ + DRI_CONF_ENUM(1,"Slaap voor korte intervallen tijdens het wachten op de grafische hardware") \ + DRI_CONF_ENUM(2,"Laat de grafische hardware een software onderbreking uitzenden en in slaap vallen") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(fr,"Méthode d'attente de la carte graphique") \ + DRI_CONF_ENUM(0,"Attente active de la carte graphique") \ + DRI_CONF_ENUM(1,"Attente utilisant usleep()") \ + DRI_CONF_ENUM(2,"Utiliser les interruptions") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(sv,"Metod för att begränsa renderingslatens") \ + DRI_CONF_ENUM(0,"Upptagen med att vänta på grafikhårdvaran") \ + DRI_CONF_ENUM(1,"Sov i korta intervall under väntan på grafikhårdvaran") \ + DRI_CONF_ENUM(2,"Låt grafikhårdvaran sända ut ett programvaruavbrott och sov") \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_VBLANK_NEVER 0 +#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 +#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 +#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 +#define DRI_CONF_VBLANK_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \ + DRI_CONF_DESC_BEGIN(en,"Synchronization with vertical refresh (swap intervals)") \ + DRI_CONF_ENUM(0,"Never synchronize with vertical refresh, ignore application's choice") \ + DRI_CONF_ENUM(1,"Initial swap interval 0, obey application's choice") \ + DRI_CONF_ENUM(2,"Initial swap interval 1, obey application's choice") \ + DRI_CONF_ENUM(3,"Always synchronize with vertical refresh, application chooses the minimum swap interval") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(ca,"Sincronització amb refresc vertical (intervals d'intercanvi)") \ + DRI_CONF_ENUM(0,"Mai sincronitzis amb el refresc vertical, ignora l'elecció de l'aplicació") \ + DRI_CONF_ENUM(1,"Interval d'intercanvi inicial 0, obeeix l'elecció de l'aplicació") \ + DRI_CONF_ENUM(2,"Interval d'intercanvi inicial 1, obeeix l'elecció de l'aplicació") \ + DRI_CONF_ENUM(3,"Sempre sincronitza amb el refresc vertical, l'aplicació tria l'interval mínim d'intercanvi") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(de,"Synchronisation mit der vertikalen Bildwiederholung") \ + DRI_CONF_ENUM(0,"Niemals mit der Bildwiederholung synchronisieren, Anweisungen der Anwendung ignorieren") \ + DRI_CONF_ENUM(1,"Initiales Bildinterval 0, Anweisungen der Anwendung gehorchen") \ + DRI_CONF_ENUM(2,"Initiales Bildinterval 1, Anweisungen der Anwendung gehorchen") \ + DRI_CONF_ENUM(3,"Immer mit der Bildwiederholung synchronisieren, Anwendung wählt das minimale Bildintervall") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(es,"Sincronización con el refresco vertical (intervalos de intercambio)") \ + DRI_CONF_ENUM(0,"No sincronizar nunca con el refresco vertical, ignorar la elección de la aplicación") \ + DRI_CONF_ENUM(1,"Intervalo de intercambio inicial 0, obedecer la elección de la aplicación") \ + DRI_CONF_ENUM(2,"Intervalo de intercambio inicial 1, obedecer la elección de la aplicación") \ + DRI_CONF_ENUM(3,"Sincronizar siempre con el refresco vertical, la aplicación elige el intervalo de intercambio mínimo") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(nl,"Synchronisatie met verticale verversing (interval omwisselen)") \ + DRI_CONF_ENUM(0,"Nooit synchroniseren met verticale verversing, negeer de keuze van de applicatie") \ + DRI_CONF_ENUM(1,"Initïeel omwisselingsinterval 0, honoreer de keuze van de applicatie") \ + DRI_CONF_ENUM(2,"Initïeel omwisselingsinterval 1, honoreer de keuze van de applicatie") \ + DRI_CONF_ENUM(3,"Synchroniseer altijd met verticale verversing, de applicatie kiest het minimum omwisselingsinterval") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(fr,"Synchronisation de l'affichage avec le balayage vertical") \ + DRI_CONF_ENUM(0,"Ne jamais synchroniser avec le balayage vertical, ignorer le choix de l'application") \ + DRI_CONF_ENUM(1,"Ne pas synchroniser avec le balayage vertical par défaut, mais obéir au choix de l'application") \ + DRI_CONF_ENUM(2,"Synchroniser avec le balayage vertical par défaut, mais obéir au choix de l'application") \ + DRI_CONF_ENUM(3,"Toujours synchroniser avec le balayage vertical, l'application choisit l'intervalle minimal") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(sv,"Synkronisering med vertikal uppdatering (växlingsintervall)") \ + DRI_CONF_ENUM(0,"Synkronisera aldrig med vertikal uppdatering, ignorera programmets val") \ + DRI_CONF_ENUM(1,"Initialt växlingsintervall 0, följ programmets val") \ + DRI_CONF_ENUM(2,"Initialt växlingsintervall 1, följ programmets val") \ + DRI_CONF_ENUM(3,"Synkronisera alltid med vertikal uppdatering, programmet väljer den minsta växlingsintervallen") \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_HYPERZ_DISABLED 0 +#define DRI_CONF_HYPERZ_ENABLED 1 +#define DRI_CONF_HYPERZ(def) \ +DRI_CONF_OPT_BEGIN_B(hyperz, def) \ + DRI_CONF_DESC(en,"Use HyperZ to boost performance") \ + DRI_CONF_DESC(ca,"Utilitza el HyperZ per a augmentar el rendiment") \ + DRI_CONF_DESC(de,"HyperZ zur Leistungssteigerung verwenden") \ + DRI_CONF_DESC(es,"Usar HyperZ para potenciar rendimiento") \ + DRI_CONF_DESC(nl,"Gebruik HyperZ om de prestaties te verbeteren") \ + DRI_CONF_DESC(fr,"Utiliser le HyperZ pour améliorer les performances") \ + DRI_CONF_DESC(sv,"Använd HyperZ för att maximera prestandan") \ +DRI_CONF_OPT_END + +#define DRI_CONF_MAX_TEXTURE_UNITS(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(texture_units,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,"Number of texture units used") \ + DRI_CONF_DESC(ca,"Nombre d'unitats de textura utilitzades") \ + DRI_CONF_DESC(de,"Anzahl der benutzten Textureinheiten") \ + DRI_CONF_DESC(es,"Número de unidades de textura usadas") \ + DRI_CONF_DESC(nl,"Aantal textuureenheden in gebruik") \ + DRI_CONF_DESC(fr,"Nombre d'unités de texture") \ + DRI_CONF_DESC(sv,"Antal använda texturenheter") \ +DRI_CONF_OPT_END + +#define DRI_CONF_TEXTURE_BLEND_QUALITY(def,range) \ +DRI_CONF_OPT_BEGIN_V(texture_blend_quality,float,def,range) \ + DRI_CONF_DESC(en,"Texture filtering quality vs. speed, AKA “brilinear” texture filtering") \ + DRI_CONF_DESC(ca,"Qualitat vs. velocitat de filtració de textura, àlies filtració ”brilinear“ de textura") \ + DRI_CONF_DESC(de,"Texturfilterqualität versus -geschwindigkeit, auch bekannt als „brilineare“ Texturfilterung") \ + DRI_CONF_DESC(es,"Calidad de filtrado de textura vs. velocidad, alias filtrado ”brilinear“ de textura") \ + DRI_CONF_DESC(nl,"Textuurfilterkwaliteit versus -snelheid, ookwel bekend als “brilineaire” textuurfiltering") \ + DRI_CONF_DESC(fr,"Qualité/performance du filtrage trilinéaire de texture (filtrage brilinéaire)") \ + DRI_CONF_DESC(sv,"Texturfiltreringskvalitet mot hastighet, även kallad ”brilinear”-texturfiltrering") \ +DRI_CONF_OPT_END + +#define DRI_CONF_TEXTURE_HEAPS_ALL 0 +#define DRI_CONF_TEXTURE_HEAPS_CARD 1 +#define DRI_CONF_TEXTURE_HEAPS_GART 2 +#define DRI_CONF_TEXTURE_HEAPS(def) \ +DRI_CONF_OPT_BEGIN_V(texture_heaps,enum,def,"0:2") \ + DRI_CONF_DESC_BEGIN(en,"Used types of texture memory") \ + DRI_CONF_ENUM(0,"All available memory") \ + DRI_CONF_ENUM(1,"Only card memory (if available)") \ + DRI_CONF_ENUM(2,"Only GART (AGP/PCIE) memory (if available)") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(ca,"Tipus utilitzats de memòria de textura") \ + DRI_CONF_ENUM(0,"Tota la memòria disponible") \ + DRI_CONF_ENUM(1,"Només memòria de targeta (si està disponible)") \ + DRI_CONF_ENUM(2,"Només memòria GART (AGP/PCIE) (si està disponible)") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(de,"Benutzte Arten von Texturspeicher") \ + DRI_CONF_ENUM(0,"Aller verfügbarer Speicher") \ + DRI_CONF_ENUM(1,"Nur Grafikspeicher (falls verfügbar)") \ + DRI_CONF_ENUM(2,"Nur GART-Speicher (AGP/PCIE) (falls verfügbar)") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(es,"Tipos de memoria de textura usados") \ + DRI_CONF_ENUM(0,"Toda la memoria disponible") \ + DRI_CONF_ENUM(1,"Solo memoria de tarjeta (si está disponible)") \ + DRI_CONF_ENUM(2,"Solo memoria GART (AGP/PCIE) (si está disponible)") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(nl,"Gebruikte soorten textuurgeheugen") \ + DRI_CONF_ENUM(0,"Al het beschikbaar geheugen") \ + DRI_CONF_ENUM(1,"Alleen geheugen op de kaart (als het aanwezig is)") \ + DRI_CONF_ENUM(2,"Alleen GART (AGP/PCIE) geheugen (als het aanwezig is)") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(fr,"Types de mémoire de texture") \ + DRI_CONF_ENUM(0,"Utiliser toute la mémoire disponible") \ + DRI_CONF_ENUM(1,"Utiliser uniquement la mémoire graphique (si disponible)") \ + DRI_CONF_ENUM(2,"Utiliser uniquement la mémoire GART (AGP/PCIE) (si disponible)") \ + DRI_CONF_DESC_END \ + DRI_CONF_DESC_BEGIN(sv,"Använda typer av texturminne") \ + DRI_CONF_ENUM(0,"Allt tillgängligt minne") \ + DRI_CONF_ENUM(1,"Endast kortminne (om tillgängligt)") \ + DRI_CONF_ENUM(2,"Endast GART-minne (AGP/PCIE) (om tillgängligt)") \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_MESA_GLTHREAD(def) \ +DRI_CONF_OPT_BEGIN_B(mesa_glthread, def) \ + DRI_CONF_DESC(en,"Enable offloading GL driver work to a separate thread") \ + DRI_CONF_DESC(ca,"Enable offloading GL driver work to a separate thread") \ + DRI_CONF_DESC(de,"Enable offloading GL driver work to a separate thread") \ + DRI_CONF_DESC(es,"Enable offloading GL driver work to a separate thread") \ + DRI_CONF_DESC(nl,"Enable offloading GL driver work to a separate thread") \ + DRI_CONF_DESC(fr,"Enable offloading GL driver work to a separate thread") \ + DRI_CONF_DESC(sv,"Enable offloading GL driver work to a separate thread") \ +DRI_CONF_OPT_END + +#define DRI_CONF_MESA_NO_ERROR(def) \ +DRI_CONF_OPT_BEGIN_B(mesa_no_error, def) \ + DRI_CONF_DESC(en,"Disable GL driver error checking") \ + DRI_CONF_DESC(ca,"Disable GL driver error checking") \ + DRI_CONF_DESC(de,"Disable GL driver error checking") \ + DRI_CONF_DESC(es,"Disable GL driver error checking") \ + DRI_CONF_DESC(nl,"Disable GL driver error checking") \ + DRI_CONF_DESC(fr,"Disable GL driver error checking") \ + DRI_CONF_DESC(sv,"Disable GL driver error checking") \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_EXT_BUFFER_AGE(def) \ +DRI_CONF_OPT_BEGIN_B(glx_disable_ext_buffer_age, def) \ + DRI_CONF_DESC(en, "Disable the GLX_EXT_buffer_age extension") \ + DRI_CONF_DESC(ca, "Disable the GLX_EXT_buffer_age extension") \ + DRI_CONF_DESC(de, "Disable the GLX_EXT_buffer_age extension") \ + DRI_CONF_DESC(es, "Disable the GLX_EXT_buffer_age extension") \ + DRI_CONF_DESC(nl, "Disable the GLX_EXT_buffer_age extension") \ + DRI_CONF_DESC(fr, "Disable the GLX_EXT_buffer_age extension") \ + DRI_CONF_DESC(sv, "Disable the GLX_EXT_buffer_age extension") \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_OML_SYNC_CONTROL(def) \ +DRI_CONF_OPT_BEGIN_B(glx_disable_oml_sync_control, def) \ + DRI_CONF_DESC(en, "Disable the GLX_OML_sync_control extension") \ + DRI_CONF_DESC(ca, "Disable the GLX_OML_sync_control extension") \ + DRI_CONF_DESC(de, "Disable the GLX_OML_sync_control extension") \ + DRI_CONF_DESC(es, "Disable the GLX_OML_sync_control extension") \ + DRI_CONF_DESC(nl, "Disable the GLX_OML_sync_control extension") \ + DRI_CONF_DESC(fr, "Disable the GLX_OML_sync_control extension") \ + DRI_CONF_DESC(sv, "Disable the GLX_OML_sync_control extension") \ +DRI_CONF_OPT_END + + +/** + * \brief Software-fallback options. To allow using features (like + * GL_ARB_vertex_program) on GPUs that don't otherwise support the feature. + */ +#define DRI_CONF_SECTION_SOFTWARE \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,"Features that are not hardware-accelerated") \ + DRI_CONF_DESC(ca,"Característiques no accelerades per maquinari") \ + DRI_CONF_DESC(de,"Funktionalität, die nicht hardwarebeschleunigt ist") \ + DRI_CONF_DESC(es,"Características no aceleradas por hardware") \ + DRI_CONF_DESC(nl,"Eigenschappen die niet hardwareversneld zijn") \ + DRI_CONF_DESC(fr,"Fonctionnalités ne bénéficiant pas d'une accélération matérielle") \ + DRI_CONF_DESC(sv,"Funktioner som inte är hårdvaruaccelererade") + +#define DRI_CONF_ARB_VERTEX_PROGRAM(def) \ +DRI_CONF_OPT_BEGIN_B(arb_vertex_program, def) \ + DRI_CONF_DESC(en,"Enable extension GL_ARB_vertex_program") \ + DRI_CONF_DESC(ca,"Habilita l'extensió GL_ARB_vertex_program") \ + DRI_CONF_DESC(de,"Erweiterung GL_ARB_vertex_program aktivieren") \ + DRI_CONF_DESC(es,"Habilitar la extensión GL_ARB_vertex_program") \ + DRI_CONF_DESC(nl,"Zet uitbreiding GL_ARB_vertex_program aan") \ + DRI_CONF_DESC(fr,"Activer l'extension GL_ARB_vertex_program") \ + DRI_CONF_DESC(sv,"Aktivera tillägget GL_ARB_vertex_program") \ +DRI_CONF_OPT_END + + + +/** + * \brief Miscellaneous configuration options + */ +#define DRI_CONF_SECTION_MISCELLANEOUS \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,"Miscellaneous") \ + DRI_CONF_DESC(ca,"Miscel·lània") \ + DRI_CONF_DESC(de,"Miscellaneous") \ + DRI_CONF_DESC(es,"Misceláneos") \ + DRI_CONF_DESC(nl,"Miscellaneous") \ + DRI_CONF_DESC(fr,"Miscellaneous") \ + DRI_CONF_DESC(sv,"Miscellaneous") + +#define DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER(def) \ +DRI_CONF_OPT_BEGIN_B(always_have_depth_buffer, def) \ + DRI_CONF_DESC(en,"Create all visuals with a depth buffer") \ + DRI_CONF_DESC(ca,"Crea tots els visuals amb buffer de profunditat") \ + DRI_CONF_DESC(de,"Create all visuals with a depth buffer") \ + DRI_CONF_DESC(es,"Crear todos los visuales con búfer de profundidad") \ + DRI_CONF_DESC(nl,"Create all visuals with a depth buffer") \ + DRI_CONF_DESC(fr,"Create all visuals with a depth buffer") \ + DRI_CONF_DESC(sv,"Create all visuals with a depth buffer") \ +DRI_CONF_OPT_END + +#define DRI_CONF_GLSL_ZERO_INIT(def) \ +DRI_CONF_OPT_BEGIN_B(glsl_zero_init, def) \ + DRI_CONF_DESC(en,"Force uninitialized variables to default to zero") \ + DRI_CONF_DESC(ca,"Force uninitialized variables to default to zero") \ + DRI_CONF_DESC(de,"Force uninitialized variables to default to zero") \ + DRI_CONF_DESC(es,"Force uninitialized variables to default to zero") \ + DRI_CONF_DESC(nl,"Force uninitialized variables to default to zero") \ + DRI_CONF_DESC(fr,"Force uninitialized variables to default to zero") \ + DRI_CONF_DESC(sv,"Force uninitialized variables to default to zero") \ +DRI_CONF_OPT_END + +/** + * \brief Initialization configuration options + */ +#define DRI_CONF_SECTION_INITIALIZATION \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,"Initialization") \ + DRI_CONF_DESC(ca,"Inicialització") \ + DRI_CONF_DESC(de,"Initialization") \ + DRI_CONF_DESC(es,"Inicialización") \ + DRI_CONF_DESC(nl,"Initialization") \ + DRI_CONF_DESC(fr,"Initialization") \ + DRI_CONF_DESC(sv,"Initialization") + +#define DRI_CONF_DEVICE_ID_PATH_TAG(def) \ +DRI_CONF_OPT_BEGIN(device_id, string, def) \ + DRI_CONF_DESC(en,"Define the graphic device to use if possible") \ + DRI_CONF_DESC(ca,"Defineix el dispositiu de gràfics que utilitzar si és possible") \ + DRI_CONF_DESC(de,"Define the graphic device to use if possible") \ + DRI_CONF_DESC(es,"Define el dispositivo de gráficos que usar si es posible") \ + DRI_CONF_DESC(nl,"Define the graphic device to use if possible") \ + DRI_CONF_DESC(fr,"Define the graphic device to use if possible") \ + DRI_CONF_DESC(sv,"Define the graphic device to use if possible") \ +DRI_CONF_OPT_END + +/** + * \brief Gallium-Nine specific configuration options + */ + +#define DRI_CONF_SECTION_NINE \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,"Gallium Nine") \ + DRI_CONF_DESC(ca,"Gallium Nine") \ + DRI_CONF_DESC(de,"Gallium Nine") \ + DRI_CONF_DESC(es,"Gallium Nine") \ + DRI_CONF_DESC(nl,"Gallium Nine") \ + DRI_CONF_DESC(fr,"Gallium Nine") \ + DRI_CONF_DESC(sv,"Gallium Nine") + +#define DRI_CONF_NINE_THROTTLE(def) \ +DRI_CONF_OPT_BEGIN(throttle_value, int, def) \ + DRI_CONF_DESC(en,"Define the throttling value. -1 for no throttling, -2 for default (usually 2), 0 for glfinish behaviour") \ + DRI_CONF_DESC(ca,"Defineix el valor de regulació. -1 per a no regular, -2 per al predeterminat (generalment 2), 0 per al comportament de glfinish") \ + DRI_CONF_DESC(de,"Define the throttling value. -1 for no throttling, -2 for default (usually 2), 0 for glfinish behaviour") \ + DRI_CONF_DESC(es,"Define el valor de regulación. -1 para no regular, -2 para el por defecto (generalmente 2), 0 para el comportamiento de glfinish") \ + DRI_CONF_DESC(nl,"Define the throttling value. -1 for no throttling, -2 for default (usually 2), 0 for glfinish behaviour") \ + DRI_CONF_DESC(fr,"Define the throttling value. -1 for no throttling, -2 for default (usually 2), 0 for glfinish behaviour") \ + DRI_CONF_DESC(sv,"Define the throttling value. -1 for no throttling, -2 for default (usually 2), 0 for glfinish behaviour") \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_THREADSUBMIT(def) \ +DRI_CONF_OPT_BEGIN_B(thread_submit, def) \ + DRI_CONF_DESC(en,"Use an additional thread to submit buffers.") \ + DRI_CONF_DESC(ca,"Utilitza un fil addicional per a entregar els buffers.") \ + DRI_CONF_DESC(de,"Use an additional thread to submit buffers.") \ + DRI_CONF_DESC(es,"Usar un hilo adicional para entregar los búfer.") \ + DRI_CONF_DESC(nl,"Use an additional thread to submit buffers.") \ + DRI_CONF_DESC(fr,"Use an additional thread to submit buffers.") \ + DRI_CONF_DESC(sv,"Use an additional thread to submit buffers.") \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_OVERRIDEVENDOR(def) \ +DRI_CONF_OPT_BEGIN(override_vendorid, int, def) \ + DRI_CONF_DESC(en,"Define the vendor_id to report. This allows faking another hardware vendor.") \ + DRI_CONF_DESC(ca,"Define the vendor_id to report. This allows faking another hardware vendor.") \ + DRI_CONF_DESC(de,"Define the vendor_id to report. This allows faking another hardware vendor.") \ + DRI_CONF_DESC(es,"Define the vendor_id to report. This allows faking another hardware vendor.") \ + DRI_CONF_DESC(nl,"Define the vendor_id to report. This allows faking another hardware vendor.") \ + DRI_CONF_DESC(fr,"Define the vendor_id to report. This allows faking another hardware vendor.") \ + DRI_CONF_DESC(sv,"Define the vendor_id to report. This allows faking another hardware vendor.") \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_ALLOWDISCARDDELAYEDRELEASE(def) \ +DRI_CONF_OPT_BEGIN_B(discard_delayed_release, def) \ + DRI_CONF_DESC(en,"Whether to allow the display server to release buffers with a delay when using d3d's presentation mode DISCARD. Default to true. Set to false if suffering from lag (thread_submit=true can also help in this situation).") \ + DRI_CONF_DESC(ca,"Whether to allow the display server to release buffers with a delay when using d3d's presentation mode DISCARD. Default to true. Set to false if suffering from lag (thread_submit=true can also help in this situation).") \ + DRI_CONF_DESC(de,"Whether to allow the display server to release buffers with a delay when using d3d's presentation mode DISCARD. Default to true. Set to false if suffering from lag (thread_submit=true can also help in this situation).") \ + DRI_CONF_DESC(es,"Whether to allow the display server to release buffers with a delay when using d3d's presentation mode DISCARD. Default to true. Set to false if suffering from lag (thread_submit=true can also help in this situation).") \ + DRI_CONF_DESC(nl,"Whether to allow the display server to release buffers with a delay when using d3d's presentation mode DISCARD. Default to true. Set to false if suffering from lag (thread_submit=true can also help in this situation).") \ + DRI_CONF_DESC(fr,"Whether to allow the display server to release buffers with a delay when using d3d's presentation mode DISCARD. Default to true. Set to false if suffering from lag (thread_submit=true can also help in this situation).") \ + DRI_CONF_DESC(sv,"Whether to allow the display server to release buffers with a delay when using d3d's presentation mode DISCARD. Default to true. Set to false if suffering from lag (thread_submit=true can also help in this situation).") \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_TEARFREEDISCARD(def) \ +DRI_CONF_OPT_BEGIN_B(tearfree_discard, def) \ + DRI_CONF_DESC(en,"Whether to make d3d's presentation mode DISCARD (games usually use that mode) Tear Free. If rendering above screen refresh, some frames will get skipped. false by default.") \ + DRI_CONF_DESC(ca,"Whether to make d3d's presentation mode DISCARD (games usually use that mode) Tear Free. If rendering above screen refresh, some frames will get skipped. false by default.") \ + DRI_CONF_DESC(de,"Whether to make d3d's presentation mode DISCARD (games usually use that mode) Tear Free. If rendering above screen refresh, some frames will get skipped. false by default.") \ + DRI_CONF_DESC(es,"Whether to make d3d's presentation mode DISCARD (games usually use that mode) Tear Free. If rendering above screen refresh, some frames will get skipped. false by default.") \ + DRI_CONF_DESC(nl,"Whether to make d3d's presentation mode DISCARD (games usually use that mode) Tear Free. If rendering above screen refresh, some frames will get skipped. false by default.") \ + DRI_CONF_DESC(fr,"Whether to make d3d's presentation mode DISCARD (games usually use that mode) Tear Free. If rendering above screen refresh, some frames will get skipped. false by default.") \ + DRI_CONF_DESC(sv,"Whether to make d3d's presentation mode DISCARD (games usually use that mode) Tear Free. If rendering above screen refresh, some frames will get skipped. false by default.") \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_CSMT(def) \ +DRI_CONF_OPT_BEGIN(csmt_force, int, def) \ + DRI_CONF_DESC(en,"If set to 1, force gallium nine CSMT. If set to 0, disable it. By default (-1) CSMT is enabled on known thread-safe drivers.") \ + DRI_CONF_DESC(ca,"If set to 1, force gallium nine CSMT. If set to 0, disable it. By default (-1) CSMT is enabled on known thread-safe drivers.") \ + DRI_CONF_DESC(de,"If set to 1, force gallium nine CSMT. If set to 0, disable it. By default (-1) CSMT is enabled on known thread-safe drivers.") \ + DRI_CONF_DESC(es,"If set to 1, force gallium nine CSMT. If set to 0, disable it. By default (-1) CSMT is enabled on known thread-safe drivers.") \ + DRI_CONF_DESC(nl,"If set to 1, force gallium nine CSMT. If set to 0, disable it. By default (-1) CSMT is enabled on known thread-safe drivers.") \ + DRI_CONF_DESC(fr,"If set to 1, force gallium nine CSMT. If set to 0, disable it. By default (-1) CSMT is enabled on known thread-safe drivers.") \ + DRI_CONF_DESC(sv,"If set to 1, force gallium nine CSMT. If set to 0, disable it. By default (-1) CSMT is enabled on known thread-safe drivers.") \ +DRI_CONF_OPT_END + +/** + * \brief radeonsi specific configuration options + */ + +#define DRI_CONF_RADEONSI_ENABLE_SISCHED(def) \ +DRI_CONF_OPT_BEGIN_B(radeonsi_enable_sisched, def) \ + DRI_CONF_DESC(en,"Use the LLVM sisched option for shader compiles") \ + DRI_CONF_DESC(ca,"Use the LLVM sisched option for shader compiles") \ + DRI_CONF_DESC(de,"Use the LLVM sisched option for shader compiles") \ + DRI_CONF_DESC(es,"Use the LLVM sisched option for shader compiles") \ + DRI_CONF_DESC(nl,"Use the LLVM sisched option for shader compiles") \ + DRI_CONF_DESC(fr,"Use the LLVM sisched option for shader compiles") \ + DRI_CONF_DESC(sv,"Use the LLVM sisched option for shader compiles") \ +DRI_CONF_OPT_END + +#define DRI_CONF_RADEONSI_ASSUME_NO_Z_FIGHTS(def) \ +DRI_CONF_OPT_BEGIN_B(radeonsi_assume_no_z_fights, def) \ + DRI_CONF_DESC(en,"Assume no Z fights (enables aggressive out-of-order rasterization to improve performance; may cause rendering errors)") \ + DRI_CONF_DESC(ca,"Assume no Z fights (enables aggressive out-of-order rasterization to improve performance; may cause rendering errors)") \ + DRI_CONF_DESC(de,"Assume no Z fights (enables aggressive out-of-order rasterization to improve performance; may cause rendering errors)") \ + DRI_CONF_DESC(es,"Assume no Z fights (enables aggressive out-of-order rasterization to improve performance; may cause rendering errors)") \ + DRI_CONF_DESC(nl,"Assume no Z fights (enables aggressive out-of-order rasterization to improve performance; may cause rendering errors)") \ + DRI_CONF_DESC(fr,"Assume no Z fights (enables aggressive out-of-order rasterization to improve performance; may cause rendering errors)") \ + DRI_CONF_DESC(sv,"Assume no Z fights (enables aggressive out-of-order rasterization to improve performance; may cause rendering errors)") \ +DRI_CONF_OPT_END + +#define DRI_CONF_RADEONSI_COMMUTATIVE_BLEND_ADD(def) \ +DRI_CONF_OPT_BEGIN_B(radeonsi_commutative_blend_add, def) \ + DRI_CONF_DESC(en,"Commutative additive blending optimizations (may cause rendering errors)") \ + DRI_CONF_DESC(ca,"Commutative additive blending optimizations (may cause rendering errors)") \ + DRI_CONF_DESC(de,"Commutative additive blending optimizations (may cause rendering errors)") \ + DRI_CONF_DESC(es,"Commutative additive blending optimizations (may cause rendering errors)") \ + DRI_CONF_DESC(nl,"Commutative additive blending optimizations (may cause rendering errors)") \ + DRI_CONF_DESC(fr,"Commutative additive blending optimizations (may cause rendering errors)") \ + DRI_CONF_DESC(sv,"Commutative additive blending optimizations (may cause rendering errors)") \ +DRI_CONF_OPT_END + +#define DRI_CONF_RADEONSI_CLEAR_DB_CACHE_BEFORE_CLEAR(def) \ +DRI_CONF_OPT_BEGIN_B(radeonsi_clear_db_cache_before_clear, def) \ + DRI_CONF_DESC(en,"Clear DB cache before fast depth clear") \ +DRI_CONF_OPT_END diff --git a/lib/mesa/src/util/xmlpool/sv.po b/lib/mesa/src/util/xmlpool/sv.po new file mode 100644 index 000000000..d8d7353f4 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/sv.po @@ -0,0 +1,309 @@ +# Swedish translation of DRI driver options. +# Copyright (C) Free Software Foundation, Inc. +# This file is distributed under the same license as the Mesa package. +# Daniel Nylander <po@danielnylander.se>, 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: Mesa DRI\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-09-25 22:29-0600\n" +"PO-Revision-Date: 2006-09-18 10:56+0100\n" +"Last-Translator: Daniel Nylander <po@danielnylander.se>\n" +"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: t_options.h:56 +msgid "Debugging" +msgstr "Felsökning" + +#: t_options.h:60 +msgid "Disable 3D acceleration" +msgstr "Inaktivera 3D-accelerering" + +#: t_options.h:65 +msgid "Show performance boxes" +msgstr "Visa prestandarutor" + +#: t_options.h:70 +msgid "Enable flushing batchbuffer after each draw call" +msgstr "" + +#: t_options.h:75 +msgid "Enable flushing GPU caches with each draw call" +msgstr "" + +#: t_options.h:80 +msgid "Disable throttling on first batch after flush" +msgstr "" + +#: t_options.h:85 +msgid "Force GLSL extension default behavior to 'warn'" +msgstr "" + +#: t_options.h:90 +msgid "Disable dual source blending" +msgstr "" + +#: t_options.h:95 +msgid "Disable backslash-based line continuations in GLSL source" +msgstr "" + +#: t_options.h:100 +msgid "Disable GL_ARB_shader_bit_encoding" +msgstr "" + +#: t_options.h:105 +msgid "" +"Force a default GLSL version for shaders that lack an explicit #version line" +msgstr "" + +#: t_options.h:110 +msgid "Allow GLSL #extension directives in the middle of shaders" +msgstr "" + +#: t_options.h:120 +msgid "Image Quality" +msgstr "Bildkvalitet" + +#: t_options.h:133 +msgid "Texture color depth" +msgstr "Färgdjup för texturer" + +#: t_options.h:134 +msgid "Prefer frame buffer color depth" +msgstr "Föredra färgdjupet för framebuffer" + +#: t_options.h:135 +msgid "Prefer 32 bits per texel" +msgstr "Föredra 32 bitar per texel" + +#: t_options.h:136 +msgid "Prefer 16 bits per texel" +msgstr "Föredra 16 bitar per texel" + +#: t_options.h:137 +msgid "Force 16 bits per texel" +msgstr "Tvinga 16 bitar per texel" + +#: t_options.h:143 +msgid "Initial maximum value for anisotropic texture filtering" +msgstr "Initialt maximalt värde för anisotropisk texturfiltrering" + +#: t_options.h:148 +msgid "Forbid negative texture LOD bias" +msgstr "Förbjud negativ LOD-kompensation för texturer" + +#: t_options.h:153 +msgid "" +"Enable S3TC texture compression even if software support is not available" +msgstr "Aktivera S3TC-texturkomprimering även om programvarustöd saknas" + +#: t_options.h:160 +msgid "Initial color reduction method" +msgstr "Initial färgminskningsmetod" + +#: t_options.h:161 +msgid "Round colors" +msgstr "Avrunda färger" + +#: t_options.h:162 +msgid "Dither colors" +msgstr "Utjämna färger" + +#: t_options.h:170 +msgid "Color rounding method" +msgstr "Färgavrundningsmetod" + +#: t_options.h:171 +msgid "Round color components downward" +msgstr "Avrunda färdkomponenter nedåt" + +#: t_options.h:172 +msgid "Round to nearest color" +msgstr "Avrunda till närmsta färg" + +#: t_options.h:181 +msgid "Color dithering method" +msgstr "Färgutjämningsmetod" + +#: t_options.h:182 +msgid "Horizontal error diffusion" +msgstr "Horisontell felspridning" + +#: t_options.h:183 +msgid "Horizontal error diffusion, reset error at line start" +msgstr "Horisontell felspridning, återställ fel vid radbörjan" + +#: t_options.h:184 +msgid "Ordered 2D color dithering" +msgstr "Ordnad 2D-färgutjämning" + +#: t_options.h:190 +msgid "Floating point depth buffer" +msgstr "Buffert för flytande punktdjup" + +#: t_options.h:195 +msgid "A post-processing filter to cel-shade the output" +msgstr "" + +#: t_options.h:200 +msgid "A post-processing filter to remove the red channel" +msgstr "" + +#: t_options.h:205 +msgid "A post-processing filter to remove the green channel" +msgstr "" + +#: t_options.h:210 +msgid "A post-processing filter to remove the blue channel" +msgstr "" + +#: t_options.h:215 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality" +msgstr "" + +#: t_options.h:220 +msgid "" +"Morphological anti-aliasing based on Jimenez\\' MLAA. 0 to disable, 8 for " +"default quality. Color version, usable with 2d GL apps" +msgstr "" + +#: t_options.h:230 +msgid "Performance" +msgstr "Prestanda" + +#: t_options.h:238 +msgid "TCL mode (Transformation, Clipping, Lighting)" +msgstr "TCL-läge (Transformation, Clipping, Lighting)" + +#: t_options.h:239 +msgid "Use software TCL pipeline" +msgstr "Använd programvaru-TCL-rörledning" + +#: t_options.h:240 +msgid "Use hardware TCL as first TCL pipeline stage" +msgstr "Använd maskinvaru-TCL som första TCL-rörledningssteg" + +#: t_options.h:241 +msgid "Bypass the TCL pipeline" +msgstr "Kringgå TCL-rörledningen" + +#: t_options.h:242 +msgid "" +"Bypass the TCL pipeline with state-based machine code generated on-the-fly" +msgstr "" +"Kringgå TCL-rörledningen med tillståndsbaserad maskinkod som direktgenereras" + +#: t_options.h:251 +msgid "Method to limit rendering latency" +msgstr "Metod för att begränsa renderingslatens" + +#: t_options.h:252 +msgid "Busy waiting for the graphics hardware" +msgstr "Upptagen med att vänta på grafikhårdvaran" + +#: t_options.h:253 +msgid "Sleep for brief intervals while waiting for the graphics hardware" +msgstr "Sov i korta intervall under väntan på grafikhårdvaran" + +#: t_options.h:254 +msgid "Let the graphics hardware emit a software interrupt and sleep" +msgstr "Låt grafikhårdvaran sända ut ett programvaruavbrott och sov" + +#: t_options.h:264 +msgid "Synchronization with vertical refresh (swap intervals)" +msgstr "Synkronisering med vertikal uppdatering (växlingsintervall)" + +#: t_options.h:265 +msgid "Never synchronize with vertical refresh, ignore application's choice" +msgstr "Synkronisera aldrig med vertikal uppdatering, ignorera programmets val" + +#: t_options.h:266 +msgid "Initial swap interval 0, obey application's choice" +msgstr "Initialt växlingsintervall 0, följ programmets val" + +#: t_options.h:267 +msgid "Initial swap interval 1, obey application's choice" +msgstr "Initialt växlingsintervall 1, följ programmets val" + +#: t_options.h:268 +msgid "" +"Always synchronize with vertical refresh, application chooses the minimum " +"swap interval" +msgstr "" +"Synkronisera alltid med vertikal uppdatering, programmet väljer den minsta " +"växlingsintervallen" + +#: t_options.h:276 +msgid "Use HyperZ to boost performance" +msgstr "Använd HyperZ för att maximera prestandan" + +#: t_options.h:281 +msgid "Number of texture units used" +msgstr "Antal använda texturenheter" + +#: t_options.h:286 +msgid "Texture filtering quality vs. speed, AKA “brilinear” texture filtering" +msgstr "" +"Texturfiltreringskvalitet mot hastighet, även kallad \"brilinear\"-" +"texturfiltrering" + +#: t_options.h:294 +msgid "Used types of texture memory" +msgstr "Använda typer av texturminne" + +#: t_options.h:295 +msgid "All available memory" +msgstr "Allt tillgängligt minne" + +#: t_options.h:296 +msgid "Only card memory (if available)" +msgstr "Endast kortminne (om tillgängligt)" + +#: t_options.h:297 +msgid "Only GART (AGP/PCIE) memory (if available)" +msgstr "Endast GART-minne (AGP/PCIE) (om tillgängligt)" + +#: t_options.h:309 +msgid "Features that are not hardware-accelerated" +msgstr "Funktioner som inte är hårdvaruaccelererade" + +#: t_options.h:313 +msgid "Enable extension GL_ARB_vertex_program" +msgstr "Aktivera tillägget GL_ARB_vertex_program" + +#: t_options.h:323 +msgid "Miscellaneous" +msgstr "" + +#: t_options.h:327 +msgid "Create all visuals with a depth buffer" +msgstr "" + +#: t_options.h:337 +msgid "Initialization" +msgstr "" + +#: t_options.h:341 +msgid "Define the graphic device to use if possible" +msgstr "" + +#~ msgid "Support larger textures not guaranteed to fit into graphics memory" +#~ msgstr "" +#~ "Stöd för större texturer är inte garanterat att passa i grafikminnet" + +#~ msgid "No" +#~ msgstr "Nej" + +#~ msgid "At least 1 texture must fit under worst-case assumptions" +#~ msgstr "Åtminstone en textur måste passa för antaget sämsta förhållande" + +#~ msgid "Announce hardware limits" +#~ msgstr "Annonsera hårdvarubegränsningar" diff --git a/lib/mesa/src/util/xmlpool/sv/LC_MESSAGES/options.mo b/lib/mesa/src/util/xmlpool/sv/LC_MESSAGES/options.mo Binary files differnew file mode 100644 index 000000000..3bf610a42 --- /dev/null +++ b/lib/mesa/src/util/xmlpool/sv/LC_MESSAGES/options.mo diff --git a/lib/mesa/src/util/xmlpool/t_options.h b/lib/mesa/src/util/xmlpool/t_options.h new file mode 100644 index 000000000..bd553085c --- /dev/null +++ b/lib/mesa/src/util/xmlpool/t_options.h @@ -0,0 +1,454 @@ +/* + * XML DRI client-side driver configuration + * Copyright (C) 2003 Felix Kuehling + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and 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 + * FELIX KUEHLING, 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 t_options.h + * \brief Templates of common options + * \author Felix Kuehling + * + * This file defines macros for common options that can be used to + * construct driConfigOptions in the drivers. This file is only a + * template containing English descriptions for options wrapped in + * gettext(). xgettext can be used to extract translatable + * strings. These strings can then be translated by anyone familiar + * with GNU gettext. gen_xmlpool.py takes this template and fills in + * all the translations. The result (options.h) is included by + * xmlpool.h which in turn can be included by drivers. + * + * The macros used to describe otions in this file are defined in + * ../xmlpool.h. + */ + +/* This is needed for xgettext to extract translatable strings. + * gen_xmlpool.py will discard this line. */ +#include <libintl.h> + +/* + * predefined option sections and options with multi-lingual descriptions + */ + + +/** + * \brief Debugging options + */ +#define DRI_CONF_SECTION_DEBUG \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,gettext("Debugging")) + +#define DRI_CONF_NO_RAST(def) \ +DRI_CONF_OPT_BEGIN_B(no_rast, def) \ + DRI_CONF_DESC(en,gettext("Disable 3D acceleration")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_PERFORMANCE_BOXES(def) \ +DRI_CONF_OPT_BEGIN_B(performance_boxes, def) \ + DRI_CONF_DESC(en,gettext("Show performance boxes")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \ +DRI_CONF_OPT_BEGIN_B(always_flush_batch, def) \ + DRI_CONF_DESC(en,gettext("Enable flushing batchbuffer after each draw call")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALWAYS_FLUSH_CACHE(def) \ +DRI_CONF_OPT_BEGIN_B(always_flush_cache, def) \ + DRI_CONF_DESC(en,gettext("Enable flushing GPU caches with each draw call")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_THROTTLING(def) \ +DRI_CONF_OPT_BEGIN_B(disable_throttling, def) \ + DRI_CONF_DESC(en,gettext("Disable throttling on first batch after flush")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN(def) \ +DRI_CONF_OPT_BEGIN_B(force_glsl_extensions_warn, def) \ + DRI_CONF_DESC(en,gettext("Force GLSL extension default behavior to 'warn'")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED(def) \ +DRI_CONF_OPT_BEGIN_B(disable_blend_func_extended, def) \ + DRI_CONF_DESC(en,gettext("Disable dual source blending")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_DUAL_COLOR_BLEND_BY_LOCATION(def) \ +DRI_CONF_OPT_BEGIN_B(dual_color_blend_by_location, def) \ + DRI_CONF_DESC(en,gettext("Identify dual color blending sources by location rather than index")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS(def) \ +DRI_CONF_OPT_BEGIN_B(disable_glsl_line_continuations, def) \ + DRI_CONF_DESC(en,gettext("Disable backslash-based line continuations in GLSL source")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_SHADER_BIT_ENCODING(def) \ +DRI_CONF_OPT_BEGIN_B(disable_shader_bit_encoding, def) \ + DRI_CONF_DESC(en,gettext("Disable GL_ARB_shader_bit_encoding")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_FORCE_GLSL_VERSION(def) \ +DRI_CONF_OPT_BEGIN_V(force_glsl_version, int, def, "0:999") \ + DRI_CONF_DESC(en,gettext("Force a default GLSL version for shaders that lack an explicit #version line")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALLOW_GLSL_EXTENSION_DIRECTIVE_MIDSHADER(def) \ +DRI_CONF_OPT_BEGIN_B(allow_glsl_extension_directive_midshader, def) \ + DRI_CONF_DESC(en,gettext("Allow GLSL #extension directives in the middle of shaders")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALLOW_GLSL_BUILTIN_VARIABLE_REDECLARATION(def) \ +DRI_CONF_OPT_BEGIN_B(allow_glsl_builtin_variable_redeclaration, def) \ + DRI_CONF_DESC(en,gettext("Allow GLSL built-in variables to be redeclared verbatim")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALLOW_HIGHER_COMPAT_VERSION(def) \ +DRI_CONF_OPT_BEGIN_B(allow_higher_compat_version, def) \ + DRI_CONF_DESC(en,gettext("Allow a higher compat profile (version 3.1+) for apps that request it")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_FORCE_GLSL_ABS_SQRT(def) \ +DRI_CONF_OPT_BEGIN_B(force_glsl_abs_sqrt, def) \ + DRI_CONF_DESC(en,gettext("Force computing the absolute value for sqrt() and inversesqrt()")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_GLSL_CORRECT_DERIVATIVES_AFTER_DISCARD(def) \ +DRI_CONF_OPT_BEGIN_B(glsl_correct_derivatives_after_discard, def) \ + DRI_CONF_DESC(en,gettext("Implicit and explicit derivatives after a discard behave as if the discard didn't happen")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_ALLOW_GLSL_CROSS_STAGE_INTERPOLATION_MISMATCH(def) \ +DRI_CONF_OPT_BEGIN_B(allow_glsl_cross_stage_interpolation_mismatch, def) \ + DRI_CONF_DESC(en,gettext("Allow interpolation qualifier mismatch across shader stages")) \ +DRI_CONF_OPT_END + +/** + * \brief Image quality-related options + */ +#define DRI_CONF_SECTION_QUALITY \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,gettext("Image Quality")) + +#define DRI_CONF_EXCESS_MIPMAP(def) \ +DRI_CONF_OPT_BEGIN_B(excess_mipmap, def) \ + DRI_CONF_DESC(en,"Enable extra mipmap level") \ +DRI_CONF_OPT_END + +#define DRI_CONF_TEXTURE_DEPTH_FB 0 +#define DRI_CONF_TEXTURE_DEPTH_32 1 +#define DRI_CONF_TEXTURE_DEPTH_16 2 +#define DRI_CONF_TEXTURE_DEPTH_FORCE_16 3 +#define DRI_CONF_TEXTURE_DEPTH(def) \ +DRI_CONF_OPT_BEGIN_V(texture_depth,enum,def,"0:3") \ + DRI_CONF_DESC_BEGIN(en,gettext("Texture color depth")) \ + DRI_CONF_ENUM(0,gettext("Prefer frame buffer color depth")) \ + DRI_CONF_ENUM(1,gettext("Prefer 32 bits per texel")) \ + DRI_CONF_ENUM(2,gettext("Prefer 16 bits per texel")) \ + DRI_CONF_ENUM(3,gettext("Force 16 bits per texel")) \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_DEF_MAX_ANISOTROPY(def,range) \ +DRI_CONF_OPT_BEGIN_V(def_max_anisotropy,float,def,range) \ + DRI_CONF_DESC(en,gettext("Initial maximum value for anisotropic texture filtering")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_NO_NEG_LOD_BIAS(def) \ +DRI_CONF_OPT_BEGIN_B(no_neg_lod_bias, def) \ + DRI_CONF_DESC(en,gettext("Forbid negative texture LOD bias")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_PRECISE_TRIG(def) \ +DRI_CONF_OPT_BEGIN_B(precise_trig, def) \ + DRI_CONF_DESC(en,gettext("Prefer accuracy over performance in trig functions")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_COLOR_REDUCTION_ROUND 0 +#define DRI_CONF_COLOR_REDUCTION_DITHER 1 +#define DRI_CONF_COLOR_REDUCTION(def) \ +DRI_CONF_OPT_BEGIN_V(color_reduction,enum,def,"0:1") \ + DRI_CONF_DESC_BEGIN(en,gettext("Initial color reduction method")) \ + DRI_CONF_ENUM(0,gettext("Round colors")) \ + DRI_CONF_ENUM(1,gettext("Dither colors")) \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_ROUND_TRUNC 0 +#define DRI_CONF_ROUND_ROUND 1 +#define DRI_CONF_ROUND_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(round_mode,enum,def,"0:1") \ + DRI_CONF_DESC_BEGIN(en,gettext("Color rounding method")) \ + DRI_CONF_ENUM(0,gettext("Round color components downward")) \ + DRI_CONF_ENUM(1,gettext("Round to nearest color")) \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_DITHER_XERRORDIFF 0 +#define DRI_CONF_DITHER_XERRORDIFFRESET 1 +#define DRI_CONF_DITHER_ORDERED 2 +#define DRI_CONF_DITHER_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(dither_mode,enum,def,"0:2") \ + DRI_CONF_DESC_BEGIN(en,gettext("Color dithering method")) \ + DRI_CONF_ENUM(0,gettext("Horizontal error diffusion")) \ + DRI_CONF_ENUM(1,gettext("Horizontal error diffusion, reset error at line start")) \ + DRI_CONF_ENUM(2,gettext("Ordered 2D color dithering")) \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_FLOAT_DEPTH(def) \ +DRI_CONF_OPT_BEGIN_B(float_depth, def) \ + DRI_CONF_DESC(en,gettext("Floating point depth buffer")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_CELSHADE(def) \ +DRI_CONF_OPT_BEGIN_V(pp_celshade,enum,def,"0:1") \ + DRI_CONF_DESC(en,gettext("A post-processing filter to cel-shade the output")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_NORED(def) \ +DRI_CONF_OPT_BEGIN_V(pp_nored,enum,def,"0:1") \ + DRI_CONF_DESC(en,gettext("A post-processing filter to remove the red channel")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_NOGREEN(def) \ +DRI_CONF_OPT_BEGIN_V(pp_nogreen,enum,def,"0:1") \ + DRI_CONF_DESC(en,gettext("A post-processing filter to remove the green channel")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_NOBLUE(def) \ +DRI_CONF_OPT_BEGIN_V(pp_noblue,enum,def,"0:1") \ + DRI_CONF_DESC(en,gettext("A post-processing filter to remove the blue channel")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_JIMENEZMLAA(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(pp_jimenezmlaa,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,gettext("Morphological anti-aliasing based on Jimenez\\\' MLAA. 0 to disable, 8 for default quality")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_PP_JIMENEZMLAA_COLOR(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(pp_jimenezmlaa_color,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,gettext("Morphological anti-aliasing based on Jimenez\\\' MLAA. 0 to disable, 8 for default quality. Color version, usable with 2d GL apps")) \ +DRI_CONF_OPT_END + + + +/** + * \brief Performance-related options + */ +#define DRI_CONF_SECTION_PERFORMANCE \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,gettext("Performance")) + +#define DRI_CONF_TCL_SW 0 +#define DRI_CONF_TCL_PIPELINED 1 +#define DRI_CONF_TCL_VTXFMT 2 +#define DRI_CONF_TCL_CODEGEN 3 +#define DRI_CONF_TCL_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(tcl_mode,enum,def,"0:3") \ + DRI_CONF_DESC_BEGIN(en,gettext("TCL mode (Transformation, Clipping, Lighting)")) \ + DRI_CONF_ENUM(0,gettext("Use software TCL pipeline")) \ + DRI_CONF_ENUM(1,gettext("Use hardware TCL as first TCL pipeline stage")) \ + DRI_CONF_ENUM(2,gettext("Bypass the TCL pipeline")) \ + DRI_CONF_ENUM(3,gettext("Bypass the TCL pipeline with state-based machine code generated on-the-fly")) \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_FTHROTTLE_BUSY 0 +#define DRI_CONF_FTHROTTLE_USLEEPS 1 +#define DRI_CONF_FTHROTTLE_IRQS 2 +#define DRI_CONF_FTHROTTLE_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(fthrottle_mode,enum,def,"0:2") \ + DRI_CONF_DESC_BEGIN(en,gettext("Method to limit rendering latency")) \ + DRI_CONF_ENUM(0,gettext("Busy waiting for the graphics hardware")) \ + DRI_CONF_ENUM(1,gettext("Sleep for brief intervals while waiting for the graphics hardware")) \ + DRI_CONF_ENUM(2,gettext("Let the graphics hardware emit a software interrupt and sleep")) \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_VBLANK_NEVER 0 +#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1 +#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2 +#define DRI_CONF_VBLANK_ALWAYS_SYNC 3 +#define DRI_CONF_VBLANK_MODE(def) \ +DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \ + DRI_CONF_DESC_BEGIN(en,gettext("Synchronization with vertical refresh (swap intervals)")) \ + DRI_CONF_ENUM(0,gettext("Never synchronize with vertical refresh, ignore application's choice")) \ + DRI_CONF_ENUM(1,gettext("Initial swap interval 0, obey application's choice")) \ + DRI_CONF_ENUM(2,gettext("Initial swap interval 1, obey application's choice")) \ + DRI_CONF_ENUM(3,gettext("Always synchronize with vertical refresh, application chooses the minimum swap interval")) \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_HYPERZ_DISABLED 0 +#define DRI_CONF_HYPERZ_ENABLED 1 +#define DRI_CONF_HYPERZ(def) \ +DRI_CONF_OPT_BEGIN_B(hyperz, def) \ + DRI_CONF_DESC(en,gettext("Use HyperZ to boost performance")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_MAX_TEXTURE_UNITS(def,min,max) \ +DRI_CONF_OPT_BEGIN_V(texture_units,int,def, # min ":" # max ) \ + DRI_CONF_DESC(en,gettext("Number of texture units used")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_TEXTURE_BLEND_QUALITY(def,range) \ +DRI_CONF_OPT_BEGIN_V(texture_blend_quality,float,def,range) \ + DRI_CONF_DESC(en,gettext("Texture filtering quality vs. speed, AKA “brilinear” texture filtering")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_TEXTURE_HEAPS_ALL 0 +#define DRI_CONF_TEXTURE_HEAPS_CARD 1 +#define DRI_CONF_TEXTURE_HEAPS_GART 2 +#define DRI_CONF_TEXTURE_HEAPS(def) \ +DRI_CONF_OPT_BEGIN_V(texture_heaps,enum,def,"0:2") \ + DRI_CONF_DESC_BEGIN(en,gettext("Used types of texture memory")) \ + DRI_CONF_ENUM(0,gettext("All available memory")) \ + DRI_CONF_ENUM(1,gettext("Only card memory (if available)")) \ + DRI_CONF_ENUM(2,gettext("Only GART (AGP/PCIE) memory (if available)")) \ + DRI_CONF_DESC_END \ +DRI_CONF_OPT_END + +#define DRI_CONF_MESA_GLTHREAD(def) \ +DRI_CONF_OPT_BEGIN_B(mesa_glthread, def) \ + DRI_CONF_DESC(en,gettext("Enable offloading GL driver work to a separate thread")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_MESA_NO_ERROR(def) \ +DRI_CONF_OPT_BEGIN_B(mesa_no_error, def) \ + DRI_CONF_DESC(en,gettext("Disable GL driver error checking")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_EXT_BUFFER_AGE(def) \ +DRI_CONF_OPT_BEGIN_B(glx_disable_ext_buffer_age, def) \ + DRI_CONF_DESC(en, gettext("Disable the GLX_EXT_buffer_age extension")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_DISABLE_OML_SYNC_CONTROL(def) \ +DRI_CONF_OPT_BEGIN_B(glx_disable_oml_sync_control, def) \ + DRI_CONF_DESC(en, gettext("Disable the GLX_OML_sync_control extension")) \ +DRI_CONF_OPT_END + + +/** + * \brief Software-fallback options. To allow using features (like + * GL_ARB_vertex_program) on GPUs that don't otherwise support the feature. + */ +#define DRI_CONF_SECTION_SOFTWARE \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,gettext("Features that are not hardware-accelerated")) + +#define DRI_CONF_ARB_VERTEX_PROGRAM(def) \ +DRI_CONF_OPT_BEGIN_B(arb_vertex_program, def) \ + DRI_CONF_DESC(en,gettext("Enable extension GL_ARB_vertex_program")) \ +DRI_CONF_OPT_END + + + +/** + * \brief Miscellaneous configuration options + */ +#define DRI_CONF_SECTION_MISCELLANEOUS \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,gettext("Miscellaneous")) + +#define DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER(def) \ +DRI_CONF_OPT_BEGIN_B(always_have_depth_buffer, def) \ + DRI_CONF_DESC(en,gettext("Create all visuals with a depth buffer")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_GLSL_ZERO_INIT(def) \ +DRI_CONF_OPT_BEGIN_B(glsl_zero_init, def) \ + DRI_CONF_DESC(en,gettext("Force uninitialized variables to default to zero")) \ +DRI_CONF_OPT_END + +/** + * \brief Initialization configuration options + */ +#define DRI_CONF_SECTION_INITIALIZATION \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,gettext("Initialization")) + +#define DRI_CONF_DEVICE_ID_PATH_TAG(def) \ +DRI_CONF_OPT_BEGIN(device_id, string, def) \ + DRI_CONF_DESC(en,gettext("Define the graphic device to use if possible")) \ +DRI_CONF_OPT_END + +/** + * \brief Gallium-Nine specific configuration options + */ + +#define DRI_CONF_SECTION_NINE \ +DRI_CONF_SECTION_BEGIN \ + DRI_CONF_DESC(en,gettext("Gallium Nine")) + +#define DRI_CONF_NINE_THROTTLE(def) \ +DRI_CONF_OPT_BEGIN(throttle_value, int, def) \ + DRI_CONF_DESC(en,gettext("Define the throttling value. -1 for no throttling, -2 for default (usually 2), 0 for glfinish behaviour")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_THREADSUBMIT(def) \ +DRI_CONF_OPT_BEGIN_B(thread_submit, def) \ + DRI_CONF_DESC(en,gettext("Use an additional thread to submit buffers.")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_OVERRIDEVENDOR(def) \ +DRI_CONF_OPT_BEGIN(override_vendorid, int, def) \ + DRI_CONF_DESC(en,gettext("Define the vendor_id to report. This allows faking another hardware vendor.")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_ALLOWDISCARDDELAYEDRELEASE(def) \ +DRI_CONF_OPT_BEGIN_B(discard_delayed_release, def) \ + DRI_CONF_DESC(en,gettext("Whether to allow the display server to release buffers with a delay when using d3d's presentation mode DISCARD. Default to true. Set to false if suffering from lag (thread_submit=true can also help in this situation).")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_TEARFREEDISCARD(def) \ +DRI_CONF_OPT_BEGIN_B(tearfree_discard, def) \ + DRI_CONF_DESC(en,gettext("Whether to make d3d's presentation mode DISCARD (games usually use that mode) Tear Free. If rendering above screen refresh, some frames will get skipped. false by default.")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_NINE_CSMT(def) \ +DRI_CONF_OPT_BEGIN(csmt_force, int, def) \ + DRI_CONF_DESC(en,gettext("If set to 1, force gallium nine CSMT. If set to 0, disable it. By default (-1) CSMT is enabled on known thread-safe drivers.")) \ +DRI_CONF_OPT_END + +/** + * \brief radeonsi specific configuration options + */ + +#define DRI_CONF_RADEONSI_ENABLE_SISCHED(def) \ +DRI_CONF_OPT_BEGIN_B(radeonsi_enable_sisched, def) \ + DRI_CONF_DESC(en,gettext("Use the LLVM sisched option for shader compiles")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_RADEONSI_ASSUME_NO_Z_FIGHTS(def) \ +DRI_CONF_OPT_BEGIN_B(radeonsi_assume_no_z_fights, def) \ + DRI_CONF_DESC(en,gettext("Assume no Z fights (enables aggressive out-of-order rasterization to improve performance; may cause rendering errors)")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_RADEONSI_COMMUTATIVE_BLEND_ADD(def) \ +DRI_CONF_OPT_BEGIN_B(radeonsi_commutative_blend_add, def) \ + DRI_CONF_DESC(en,gettext("Commutative additive blending optimizations (may cause rendering errors)")) \ +DRI_CONF_OPT_END + +#define DRI_CONF_RADEONSI_CLEAR_DB_CACHE_BEFORE_CLEAR(def) \ +DRI_CONF_OPT_BEGIN_B(radeonsi_clear_db_cache_before_clear, def) \ + DRI_CONF_DESC(en,"Clear DB cache before fast depth clear") \ +DRI_CONF_OPT_END diff --git a/lib/mesa/src/vulkan/registry/vk_android_native_buffer.xml b/lib/mesa/src/vulkan/registry/vk_android_native_buffer.xml new file mode 100644 index 000000000..2738908aa --- /dev/null +++ b/lib/mesa/src/vulkan/registry/vk_android_native_buffer.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> +<registry> + <types> + <type category="struct" name="VkNativeBufferANDROID"> + <member values="VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID"><type>VkStructureType</type> <name>sType</name></member> + <member>const <type>void</type>* <name>pNext</name></member> + <member><type>buffer_handle_t</type> <name>handle</name></member> + <member><type>int</type> <name>stride</name></member> + <member><type>int</type> <name>format</name></member> + <member><type>int</type> <name>usage</name></member> + </type> + </types> + <commands> + <command> + <proto><type>VkResult</type> <name>vkGetSwapchainGrallocUsageANDROID</name></proto> + <param><type>VkDevice</type> <name>device</name></param> + <param><type>VkFormat</type> <name>format</name></param> + <param><type>VkImageUsageFlags</type> <name>imageUsage</name></param> + <param><type>int</type>* <name>grallocUsage</name></param> + </command> + <command> + <proto><type>VkResult</type> <name>vkAcquireImageANDROID</name></proto> + <param><type>VkDevice</type> <name>device</name></param> + <param><type>VkImage</type> <name>image</name></param> + <param><type>int</type> <name>nativeFenceFd</name></param> + <param><type>VkSemaphore</type> <name>semaphore</name></param> + <param><type>VkFence</type> <name>fence</name></param> + </command> + <command> + <proto><type>VkResult</type> <name>vkQueueSignalReleaseImageANDROID</name></proto> + <param><type>VkQueue</type> <name>queue</name></param> + <param><type>uint32_t</type> <name>waitSemaphoreCount</name></param> + <param>const <type>VkSemaphore</type>* <name>pWaitSemaphores</name></param> + <param><type>VkImage</type> <name>image</name></param> + <param><type>int</type>* <name>pNativeFenceFd</name></param> + </command> + </commands> + <extensions> + <extension name="VK_ANDROID_native_buffer" number="11" type="device" protect="ANDROID" supported="vulkan"> + <require> + <enum value="5" name="VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION"/> + <enum value="11" name="VK_ANDROID_NATIVE_BUFFER_NUMBER"/> + <enum value=""VK_ANDROID_native_buffer"" name="VK_ANDROID_NATIVE_BUFFER_NAME"/> + <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID"/> + <type name="VkNativeBufferANDROID"/> + <command name="vkGetSwapchainGrallocUsageANDROID"/> + <command name="vkAcquireImageANDROID"/> + <command name="vkQueueSignalReleaseImageANDROID"/> + </require> + </extension> + </extensions> +</registry> |