1cdc920a0Smrg/************************************************************************** 201e04c3fSmrg * 3af69d88dSmrg * Copyright 2007 VMware, Inc. 4cdc920a0Smrg * All Rights Reserved. 501e04c3fSmrg * 6cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7cdc920a0Smrg * copy of this software and associated documentation files (the 8cdc920a0Smrg * "Software"), to deal in the Software without restriction, including 9cdc920a0Smrg * without limitation the rights to use, copy, modify, merge, publish, 10cdc920a0Smrg * distribute, sub license, and/or sell copies of the Software, and to 11cdc920a0Smrg * permit persons to whom the Software is furnished to do so, subject to 12cdc920a0Smrg * the following conditions: 1301e04c3fSmrg * 14cdc920a0Smrg * The above copyright notice and this permission notice (including the 15cdc920a0Smrg * next paragraph) shall be included in all copies or substantial portions 16cdc920a0Smrg * of the Software. 1701e04c3fSmrg * 18cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20cdc920a0Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22cdc920a0Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23cdc920a0Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24cdc920a0Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2501e04c3fSmrg * 26cdc920a0Smrg **************************************************************************/ 27cdc920a0Smrg 28cdc920a0Smrg#ifndef U_INLINES_H 29cdc920a0Smrg#define U_INLINES_H 30cdc920a0Smrg 31cdc920a0Smrg#include "pipe/p_context.h" 32cdc920a0Smrg#include "pipe/p_defines.h" 33af69d88dSmrg#include "pipe/p_shader_tokens.h" 34cdc920a0Smrg#include "pipe/p_state.h" 35cdc920a0Smrg#include "pipe/p_screen.h" 367ec681f3Smrg#include "util/compiler.h" 377ec681f3Smrg#include "util/format/u_format.h" 38cdc920a0Smrg#include "util/u_debug.h" 393464ebd5Sriastradh#include "util/u_debug_describe.h" 403464ebd5Sriastradh#include "util/u_debug_refcnt.h" 41cdc920a0Smrg#include "util/u_atomic.h" 423464ebd5Sriastradh#include "util/u_box.h" 433464ebd5Sriastradh#include "util/u_math.h" 44cdc920a0Smrg 45cdc920a0Smrg 46cdc920a0Smrg#ifdef __cplusplus 47cdc920a0Smrgextern "C" { 48cdc920a0Smrg#endif 49cdc920a0Smrg 50cdc920a0Smrg 51cdc920a0Smrg/* 52cdc920a0Smrg * Reference counting helper functions. 53cdc920a0Smrg */ 54cdc920a0Smrg 55cdc920a0Smrg 5601e04c3fSmrgstatic inline void 5701e04c3fSmrgpipe_reference_init(struct pipe_reference *dst, unsigned count) 58cdc920a0Smrg{ 597ec681f3Smrg dst->count = count; 60cdc920a0Smrg} 61cdc920a0Smrg 6201e04c3fSmrgstatic inline boolean 6301e04c3fSmrgpipe_is_referenced(struct pipe_reference *src) 64cdc920a0Smrg{ 6501e04c3fSmrg return p_atomic_read(&src->count) != 0; 66cdc920a0Smrg} 67cdc920a0Smrg 68cdc920a0Smrg/** 69cdc920a0Smrg * Update reference counting. 70cdc920a0Smrg * The old thing pointed to, if any, will be unreferenced. 7101e04c3fSmrg * Both 'dst' and 'src' may be NULL. 72cdc920a0Smrg * \return TRUE if the object's refcount hits zero and should be destroyed. 73cdc920a0Smrg */ 7401e04c3fSmrgstatic inline boolean 7501e04c3fSmrgpipe_reference_described(struct pipe_reference *dst, 7601e04c3fSmrg struct pipe_reference *src, 773464ebd5Sriastradh debug_reference_descriptor get_desc) 78cdc920a0Smrg{ 7901e04c3fSmrg if (dst != src) { 8001e04c3fSmrg /* bump the src.count first */ 8101e04c3fSmrg if (src) { 827ec681f3Smrg ASSERTED int count = p_atomic_inc_return(&src->count); 8301e04c3fSmrg assert(count != 1); /* src had to be referenced */ 8401e04c3fSmrg debug_reference(src, get_desc, 1); 85cdc920a0Smrg } 86cdc920a0Smrg 8701e04c3fSmrg if (dst) { 8801e04c3fSmrg int count = p_atomic_dec_return(&dst->count); 8901e04c3fSmrg assert(count != -1); /* dst had to be referenced */ 9001e04c3fSmrg debug_reference(dst, get_desc, -1); 9101e04c3fSmrg if (!count) 9201e04c3fSmrg return true; 93cdc920a0Smrg } 94cdc920a0Smrg } 95cdc920a0Smrg 9601e04c3fSmrg return false; 97cdc920a0Smrg} 98cdc920a0Smrg 9901e04c3fSmrgstatic inline boolean 10001e04c3fSmrgpipe_reference(struct pipe_reference *dst, struct pipe_reference *src) 101cdc920a0Smrg{ 10201e04c3fSmrg return pipe_reference_described(dst, src, 10301e04c3fSmrg (debug_reference_descriptor) 10401e04c3fSmrg debug_describe_reference); 105cdc920a0Smrg} 106cdc920a0Smrg 10701e04c3fSmrgstatic inline void 10801e04c3fSmrgpipe_surface_reference(struct pipe_surface **dst, struct pipe_surface *src) 109cdc920a0Smrg{ 11001e04c3fSmrg struct pipe_surface *old_dst = *dst; 111cdc920a0Smrg 1127ec681f3Smrg if (pipe_reference_described(old_dst ? &old_dst->reference : NULL, 1137ec681f3Smrg src ? &src->reference : NULL, 11401e04c3fSmrg (debug_reference_descriptor) 11501e04c3fSmrg debug_describe_surface)) 11601e04c3fSmrg old_dst->context->surface_destroy(old_dst->context, old_dst); 11701e04c3fSmrg *dst = src; 118cdc920a0Smrg} 119cdc920a0Smrg 120af69d88dSmrg/** 121af69d88dSmrg * Similar to pipe_surface_reference() but always set the pointer to NULL 122af69d88dSmrg * and pass in an explicit context. The explicit context avoids the problem 123af69d88dSmrg * of using a deleted context's surface_destroy() method when freeing a surface 124af69d88dSmrg * that's shared by multiple contexts. 125af69d88dSmrg */ 12601e04c3fSmrgstatic inline void 127af69d88dSmrgpipe_surface_release(struct pipe_context *pipe, struct pipe_surface **ptr) 128af69d88dSmrg{ 12901e04c3fSmrg struct pipe_surface *old = *ptr; 13001e04c3fSmrg 13101e04c3fSmrg if (pipe_reference_described(&old->reference, NULL, 13201e04c3fSmrg (debug_reference_descriptor) 13301e04c3fSmrg debug_describe_surface)) 13401e04c3fSmrg pipe->surface_destroy(pipe, old); 135af69d88dSmrg *ptr = NULL; 136af69d88dSmrg} 137af69d88dSmrg 1387ec681f3Smrgstatic inline void 1397ec681f3Smrgpipe_resource_destroy(struct pipe_resource *res) 1407ec681f3Smrg{ 1417ec681f3Smrg /* Avoid recursion, which would prevent inlining this function */ 1427ec681f3Smrg do { 1437ec681f3Smrg struct pipe_resource *next = res->next; 1447ec681f3Smrg 1457ec681f3Smrg res->screen->resource_destroy(res->screen, res); 1467ec681f3Smrg res = next; 1477ec681f3Smrg } while (pipe_reference_described(res ? &res->reference : NULL, 1487ec681f3Smrg NULL, 1497ec681f3Smrg (debug_reference_descriptor) 1507ec681f3Smrg debug_describe_resource)); 1517ec681f3Smrg} 152af69d88dSmrg 15301e04c3fSmrgstatic inline void 15401e04c3fSmrgpipe_resource_reference(struct pipe_resource **dst, struct pipe_resource *src) 155cdc920a0Smrg{ 15601e04c3fSmrg struct pipe_resource *old_dst = *dst; 157cdc920a0Smrg 1587ec681f3Smrg if (pipe_reference_described(old_dst ? &old_dst->reference : NULL, 1597ec681f3Smrg src ? &src->reference : NULL, 16001e04c3fSmrg (debug_reference_descriptor) 16101e04c3fSmrg debug_describe_resource)) { 1627ec681f3Smrg pipe_resource_destroy(old_dst); 16301e04c3fSmrg } 16401e04c3fSmrg *dst = src; 165cdc920a0Smrg} 166cdc920a0Smrg 1677ec681f3Smrg/** 1687ec681f3Smrg * Subtract the given number of references. 1697ec681f3Smrg */ 1707ec681f3Smrgstatic inline void 1717ec681f3Smrgpipe_drop_resource_references(struct pipe_resource *dst, int num_refs) 1727ec681f3Smrg{ 1737ec681f3Smrg int count = p_atomic_add_return(&dst->reference.count, -num_refs); 1747ec681f3Smrg 1757ec681f3Smrg assert(count >= 0); 1767ec681f3Smrg /* Underflows shouldn't happen, but let's be safe. */ 1777ec681f3Smrg if (count <= 0) 1787ec681f3Smrg pipe_resource_destroy(dst); 1797ec681f3Smrg} 1807ec681f3Smrg 18101e04c3fSmrg/** 18201e04c3fSmrg * Same as pipe_surface_release, but used when pipe_context doesn't exist 18301e04c3fSmrg * anymore. 18401e04c3fSmrg */ 18501e04c3fSmrgstatic inline void 18601e04c3fSmrgpipe_surface_release_no_context(struct pipe_surface **ptr) 1873464ebd5Sriastradh{ 18801e04c3fSmrg struct pipe_surface *surf = *ptr; 1893464ebd5Sriastradh 19001e04c3fSmrg if (pipe_reference_described(&surf->reference, NULL, 19101e04c3fSmrg (debug_reference_descriptor) 19201e04c3fSmrg debug_describe_surface)) { 19301e04c3fSmrg /* trivially destroy pipe_surface */ 19401e04c3fSmrg pipe_resource_reference(&surf->texture, NULL); 19501e04c3fSmrg free(surf); 19601e04c3fSmrg } 19701e04c3fSmrg *ptr = NULL; 19801e04c3fSmrg} 19901e04c3fSmrg 20001e04c3fSmrg/** 20101e04c3fSmrg * Set *dst to \p src with proper reference counting. 20201e04c3fSmrg * 20301e04c3fSmrg * The caller must guarantee that \p src and *dst were created in 20401e04c3fSmrg * the same context (if they exist), and that this must be the current context. 20501e04c3fSmrg */ 20601e04c3fSmrgstatic inline void 20701e04c3fSmrgpipe_sampler_view_reference(struct pipe_sampler_view **dst, 20801e04c3fSmrg struct pipe_sampler_view *src) 20901e04c3fSmrg{ 21001e04c3fSmrg struct pipe_sampler_view *old_dst = *dst; 21101e04c3fSmrg 2127ec681f3Smrg if (pipe_reference_described(old_dst ? &old_dst->reference : NULL, 2137ec681f3Smrg src ? &src->reference : NULL, 21401e04c3fSmrg (debug_reference_descriptor) 21501e04c3fSmrg debug_describe_sampler_view)) 21601e04c3fSmrg old_dst->context->sampler_view_destroy(old_dst->context, old_dst); 21701e04c3fSmrg *dst = src; 2183464ebd5Sriastradh} 2193464ebd5Sriastradh 22001e04c3fSmrgstatic inline void 22101e04c3fSmrgpipe_so_target_reference(struct pipe_stream_output_target **dst, 22201e04c3fSmrg struct pipe_stream_output_target *src) 223af69d88dSmrg{ 22401e04c3fSmrg struct pipe_stream_output_target *old_dst = *dst; 225af69d88dSmrg 2267ec681f3Smrg if (pipe_reference_described(old_dst ? &old_dst->reference : NULL, 2277ec681f3Smrg src ? &src->reference : NULL, 228af69d88dSmrg (debug_reference_descriptor)debug_describe_so_target)) 22901e04c3fSmrg old_dst->context->stream_output_target_destroy(old_dst->context, old_dst); 23001e04c3fSmrg *dst = src; 231af69d88dSmrg} 232af69d88dSmrg 2337ec681f3Smrgstatic inline void 2347ec681f3Smrgpipe_vertex_state_reference(struct pipe_vertex_state **dst, 2357ec681f3Smrg struct pipe_vertex_state *src) 2367ec681f3Smrg{ 2377ec681f3Smrg struct pipe_vertex_state *old_dst = *dst; 2387ec681f3Smrg 2397ec681f3Smrg if (pipe_reference(old_dst ? &old_dst->reference : NULL, 2407ec681f3Smrg src ? &src->reference : NULL)) 2417ec681f3Smrg old_dst->screen->vertex_state_destroy(old_dst->screen, old_dst); 2427ec681f3Smrg *dst = src; 2437ec681f3Smrg} 2447ec681f3Smrg 24501e04c3fSmrgstatic inline void 24601e04c3fSmrgpipe_vertex_buffer_unreference(struct pipe_vertex_buffer *dst) 24701e04c3fSmrg{ 24801e04c3fSmrg if (dst->is_user_buffer) 24901e04c3fSmrg dst->buffer.user = NULL; 25001e04c3fSmrg else 25101e04c3fSmrg pipe_resource_reference(&dst->buffer.resource, NULL); 25201e04c3fSmrg} 25301e04c3fSmrg 25401e04c3fSmrgstatic inline void 25501e04c3fSmrgpipe_vertex_buffer_reference(struct pipe_vertex_buffer *dst, 25601e04c3fSmrg const struct pipe_vertex_buffer *src) 25701e04c3fSmrg{ 2587ec681f3Smrg if (dst->buffer.resource == src->buffer.resource) { 2597ec681f3Smrg /* Just copy the fields, don't touch reference counts. */ 2607ec681f3Smrg dst->stride = src->stride; 2617ec681f3Smrg dst->is_user_buffer = src->is_user_buffer; 2627ec681f3Smrg dst->buffer_offset = src->buffer_offset; 2637ec681f3Smrg return; 2647ec681f3Smrg } 2657ec681f3Smrg 26601e04c3fSmrg pipe_vertex_buffer_unreference(dst); 2677ec681f3Smrg /* Don't use memcpy because there is a hole between variables. 2687ec681f3Smrg * dst can be used as a hash key. 2697ec681f3Smrg */ 2707ec681f3Smrg dst->stride = src->stride; 2717ec681f3Smrg dst->is_user_buffer = src->is_user_buffer; 2727ec681f3Smrg dst->buffer_offset = src->buffer_offset; 2737ec681f3Smrg 2747ec681f3Smrg if (src->is_user_buffer) 2757ec681f3Smrg dst->buffer.user = src->buffer.user; 2767ec681f3Smrg else 27701e04c3fSmrg pipe_resource_reference(&dst->buffer.resource, src->buffer.resource); 27801e04c3fSmrg} 27901e04c3fSmrg 28001e04c3fSmrgstatic inline void 2813464ebd5Sriastradhpipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps, 282af69d88dSmrg struct pipe_resource *pt, unsigned level, unsigned layer) 2833464ebd5Sriastradh{ 2843464ebd5Sriastradh pipe_resource_reference(&ps->texture, pt); 2853464ebd5Sriastradh ps->format = pt->format; 2863464ebd5Sriastradh ps->width = u_minify(pt->width0, level); 2873464ebd5Sriastradh ps->height = u_minify(pt->height0, level); 2883464ebd5Sriastradh ps->u.tex.level = level; 2893464ebd5Sriastradh ps->u.tex.first_layer = ps->u.tex.last_layer = layer; 2903464ebd5Sriastradh ps->context = ctx; 2913464ebd5Sriastradh} 2923464ebd5Sriastradh 29301e04c3fSmrgstatic inline void 2943464ebd5Sriastradhpipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps, 295af69d88dSmrg struct pipe_resource *pt, unsigned level, unsigned layer) 2963464ebd5Sriastradh{ 2973464ebd5Sriastradh ps->texture = 0; 2983464ebd5Sriastradh pipe_reference_init(&ps->reference, 1); 299af69d88dSmrg pipe_surface_reset(ctx, ps, pt, level, layer); 3003464ebd5Sriastradh} 3013464ebd5Sriastradh 3023464ebd5Sriastradh/* Return true if the surfaces are equal. */ 30301e04c3fSmrgstatic inline boolean 3043464ebd5Sriastradhpipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2) 3053464ebd5Sriastradh{ 3063464ebd5Sriastradh return s1->texture == s2->texture && 3073464ebd5Sriastradh s1->format == s2->format && 3083464ebd5Sriastradh (s1->texture->target != PIPE_BUFFER || 3093464ebd5Sriastradh (s1->u.buf.first_element == s2->u.buf.first_element && 3103464ebd5Sriastradh s1->u.buf.last_element == s2->u.buf.last_element)) && 3113464ebd5Sriastradh (s1->texture->target == PIPE_BUFFER || 3123464ebd5Sriastradh (s1->u.tex.level == s2->u.tex.level && 3133464ebd5Sriastradh s1->u.tex.first_layer == s2->u.tex.first_layer && 3143464ebd5Sriastradh s1->u.tex.last_layer == s2->u.tex.last_layer)); 3153464ebd5Sriastradh} 316cdc920a0Smrg 317cdc920a0Smrg/* 318cdc920a0Smrg * Convenience wrappers for screen buffer functions. 319cdc920a0Smrg */ 320cdc920a0Smrg 321af69d88dSmrg 322af69d88dSmrg/** 323af69d88dSmrg * Create a new resource. 324af69d88dSmrg * \param bind bitmask of PIPE_BIND_x flags 32501e04c3fSmrg * \param usage a PIPE_USAGE_x value 326af69d88dSmrg */ 32701e04c3fSmrgstatic inline struct pipe_resource * 32801e04c3fSmrgpipe_buffer_create(struct pipe_screen *screen, 32901e04c3fSmrg unsigned bind, 33001e04c3fSmrg enum pipe_resource_usage usage, 33101e04c3fSmrg unsigned size) 332cdc920a0Smrg{ 3333464ebd5Sriastradh struct pipe_resource buffer; 3343464ebd5Sriastradh memset(&buffer, 0, sizeof buffer); 3353464ebd5Sriastradh buffer.target = PIPE_BUFFER; 3363464ebd5Sriastradh buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */ 3373464ebd5Sriastradh buffer.bind = bind; 3383464ebd5Sriastradh buffer.usage = usage; 3393464ebd5Sriastradh buffer.flags = 0; 3403464ebd5Sriastradh buffer.width0 = size; 3413464ebd5Sriastradh buffer.height0 = 1; 3423464ebd5Sriastradh buffer.depth0 = 1; 3433464ebd5Sriastradh buffer.array_size = 1; 3443464ebd5Sriastradh return screen->resource_create(screen, &buffer); 345cdc920a0Smrg} 346cdc920a0Smrg 3473464ebd5Sriastradh 34801e04c3fSmrgstatic inline struct pipe_resource * 34901e04c3fSmrgpipe_buffer_create_const0(struct pipe_screen *screen, 35001e04c3fSmrg unsigned bind, 35101e04c3fSmrg enum pipe_resource_usage usage, 35201e04c3fSmrg unsigned size) 35301e04c3fSmrg{ 35401e04c3fSmrg struct pipe_resource buffer; 35501e04c3fSmrg memset(&buffer, 0, sizeof buffer); 35601e04c3fSmrg buffer.target = PIPE_BUFFER; 35701e04c3fSmrg buffer.format = PIPE_FORMAT_R8_UNORM; 35801e04c3fSmrg buffer.bind = bind; 35901e04c3fSmrg buffer.usage = usage; 36001e04c3fSmrg buffer.flags = screen->get_param(screen, PIPE_CAP_CONSTBUF0_FLAGS); 36101e04c3fSmrg buffer.width0 = size; 36201e04c3fSmrg buffer.height0 = 1; 36301e04c3fSmrg buffer.depth0 = 1; 36401e04c3fSmrg buffer.array_size = 1; 36501e04c3fSmrg return screen->resource_create(screen, &buffer); 36601e04c3fSmrg} 36701e04c3fSmrg 36801e04c3fSmrg 369af69d88dSmrg/** 370af69d88dSmrg * Map a range of a resource. 37101e04c3fSmrg * \param offset start of region, in bytes 37201e04c3fSmrg * \param length size of region, in bytes 3737ec681f3Smrg * \param access bitmask of PIPE_MAP_x flags 374af69d88dSmrg * \param transfer returns a transfer object 375af69d88dSmrg */ 37601e04c3fSmrgstatic inline void * 3773464ebd5Sriastradhpipe_buffer_map_range(struct pipe_context *pipe, 37801e04c3fSmrg struct pipe_resource *buffer, 37901e04c3fSmrg unsigned offset, 38001e04c3fSmrg unsigned length, 38101e04c3fSmrg unsigned access, 38201e04c3fSmrg struct pipe_transfer **transfer) 383cdc920a0Smrg{ 3843464ebd5Sriastradh struct pipe_box box; 3853464ebd5Sriastradh void *map; 3863464ebd5Sriastradh 3873464ebd5Sriastradh assert(offset < buffer->width0); 3883464ebd5Sriastradh assert(offset + length <= buffer->width0); 3893464ebd5Sriastradh assert(length); 3903464ebd5Sriastradh 3913464ebd5Sriastradh u_box_1d(offset, length, &box); 3923464ebd5Sriastradh 3937ec681f3Smrg map = pipe->buffer_map(pipe, buffer, 0, access, &box, transfer); 39401e04c3fSmrg if (!map) { 3953464ebd5Sriastradh return NULL; 396cdc920a0Smrg } 3973464ebd5Sriastradh 398af69d88dSmrg return map; 399cdc920a0Smrg} 400cdc920a0Smrg 4013464ebd5Sriastradh 402af69d88dSmrg/** 403af69d88dSmrg * Map whole resource. 4047ec681f3Smrg * \param access bitmask of PIPE_MAP_x flags 405af69d88dSmrg * \param transfer returns a transfer object 406af69d88dSmrg */ 40701e04c3fSmrgstatic inline void * 4083464ebd5Sriastradhpipe_buffer_map(struct pipe_context *pipe, 4093464ebd5Sriastradh struct pipe_resource *buffer, 410af69d88dSmrg unsigned access, 4113464ebd5Sriastradh struct pipe_transfer **transfer) 412cdc920a0Smrg{ 41301e04c3fSmrg return pipe_buffer_map_range(pipe, buffer, 0, buffer->width0, 41401e04c3fSmrg access, transfer); 415cdc920a0Smrg} 416cdc920a0Smrg 4173464ebd5Sriastradh 41801e04c3fSmrgstatic inline void 4193464ebd5Sriastradhpipe_buffer_unmap(struct pipe_context *pipe, 4203464ebd5Sriastradh struct pipe_transfer *transfer) 421cdc920a0Smrg{ 4227ec681f3Smrg pipe->buffer_unmap(pipe, transfer); 423cdc920a0Smrg} 424cdc920a0Smrg 42501e04c3fSmrgstatic inline void 4263464ebd5Sriastradhpipe_buffer_flush_mapped_range(struct pipe_context *pipe, 4273464ebd5Sriastradh struct pipe_transfer *transfer, 428cdc920a0Smrg unsigned offset, 429cdc920a0Smrg unsigned length) 430cdc920a0Smrg{ 4313464ebd5Sriastradh struct pipe_box box; 4323464ebd5Sriastradh int transfer_offset; 4333464ebd5Sriastradh 434cdc920a0Smrg assert(length); 435af69d88dSmrg assert(transfer->box.x <= (int) offset); 436af69d88dSmrg assert((int) (offset + length) <= transfer->box.x + transfer->box.width); 4373464ebd5Sriastradh 4383464ebd5Sriastradh /* Match old screen->buffer_flush_mapped_range() behaviour, where 4393464ebd5Sriastradh * offset parameter is relative to the start of the buffer, not the 4403464ebd5Sriastradh * mapped range. 4413464ebd5Sriastradh */ 4423464ebd5Sriastradh transfer_offset = offset - transfer->box.x; 4433464ebd5Sriastradh 4443464ebd5Sriastradh u_box_1d(transfer_offset, length, &box); 4453464ebd5Sriastradh 4463464ebd5Sriastradh pipe->transfer_flush_region(pipe, transfer, &box); 447cdc920a0Smrg} 448cdc920a0Smrg 44901e04c3fSmrgstatic inline void 4503464ebd5Sriastradhpipe_buffer_write(struct pipe_context *pipe, 4513464ebd5Sriastradh struct pipe_resource *buf, 4523464ebd5Sriastradh unsigned offset, 4533464ebd5Sriastradh unsigned size, 454cdc920a0Smrg const void *data) 455cdc920a0Smrg{ 45601e04c3fSmrg /* Don't set any other usage bits. Drivers should derive them. */ 4577ec681f3Smrg pipe->buffer_subdata(pipe, buf, PIPE_MAP_WRITE, offset, size, data); 458cdc920a0Smrg} 459cdc920a0Smrg 460cdc920a0Smrg/** 461cdc920a0Smrg * Special case for writing non-overlapping ranges. 462cdc920a0Smrg * 463cdc920a0Smrg * We can avoid GPU/CPU synchronization when writing range that has never 464cdc920a0Smrg * been written before. 465cdc920a0Smrg */ 46601e04c3fSmrgstatic inline void 4673464ebd5Sriastradhpipe_buffer_write_nooverlap(struct pipe_context *pipe, 4683464ebd5Sriastradh struct pipe_resource *buf, 469cdc920a0Smrg unsigned offset, unsigned size, 470cdc920a0Smrg const void *data) 471cdc920a0Smrg{ 47201e04c3fSmrg pipe->buffer_subdata(pipe, buf, 4737ec681f3Smrg (PIPE_MAP_WRITE | 4747ec681f3Smrg PIPE_MAP_UNSYNCHRONIZED), 47501e04c3fSmrg offset, size, data); 476cdc920a0Smrg} 477cdc920a0Smrg 4787ec681f3Smrg/** 4797ec681f3Smrg * Utility for simplifying pipe_context::resource_copy_region calls 4807ec681f3Smrg */ 4817ec681f3Smrgstatic inline void 4827ec681f3Smrgpipe_buffer_copy(struct pipe_context *pipe, 4837ec681f3Smrg struct pipe_resource *dst, 4847ec681f3Smrg struct pipe_resource *src, 4857ec681f3Smrg unsigned dst_offset, 4867ec681f3Smrg unsigned src_offset, 4877ec681f3Smrg unsigned size) 4887ec681f3Smrg{ 4897ec681f3Smrg struct pipe_box box; 4907ec681f3Smrg /* only these fields are used */ 4917ec681f3Smrg box.x = (int)src_offset; 4927ec681f3Smrg box.width = (int)size; 4937ec681f3Smrg pipe->resource_copy_region(pipe, dst, 0, dst_offset, 0, 0, src, 0, &box); 4947ec681f3Smrg} 495af69d88dSmrg 496af69d88dSmrg/** 497af69d88dSmrg * Create a new resource and immediately put data into it 498af69d88dSmrg * \param bind bitmask of PIPE_BIND_x flags 499af69d88dSmrg * \param usage bitmask of PIPE_USAGE_x flags 500af69d88dSmrg */ 50101e04c3fSmrgstatic inline struct pipe_resource * 502af69d88dSmrgpipe_buffer_create_with_data(struct pipe_context *pipe, 503af69d88dSmrg unsigned bind, 50401e04c3fSmrg enum pipe_resource_usage usage, 505af69d88dSmrg unsigned size, 506af69d88dSmrg const void *ptr) 507af69d88dSmrg{ 508af69d88dSmrg struct pipe_resource *res = pipe_buffer_create(pipe->screen, 509af69d88dSmrg bind, usage, size); 510af69d88dSmrg pipe_buffer_write_nooverlap(pipe, res, 0, size, ptr); 511af69d88dSmrg return res; 512af69d88dSmrg} 513af69d88dSmrg 51401e04c3fSmrgstatic inline void 5153464ebd5Sriastradhpipe_buffer_read(struct pipe_context *pipe, 5163464ebd5Sriastradh struct pipe_resource *buf, 5173464ebd5Sriastradh unsigned offset, 5183464ebd5Sriastradh unsigned size, 519cdc920a0Smrg void *data) 520cdc920a0Smrg{ 5213464ebd5Sriastradh struct pipe_transfer *src_transfer; 5223464ebd5Sriastradh ubyte *map; 5233464ebd5Sriastradh 5243464ebd5Sriastradh map = (ubyte *) pipe_buffer_map_range(pipe, 52501e04c3fSmrg buf, 52601e04c3fSmrg offset, size, 5277ec681f3Smrg PIPE_MAP_READ, 52801e04c3fSmrg &src_transfer); 529af69d88dSmrg if (!map) 530af69d88dSmrg return; 5313464ebd5Sriastradh 532af69d88dSmrg memcpy(data, map, size); 5333464ebd5Sriastradh pipe_buffer_unmap(pipe, src_transfer); 5343464ebd5Sriastradh} 5353464ebd5Sriastradh 536af69d88dSmrg 537af69d88dSmrg/** 538af69d88dSmrg * Map a resource for reading/writing. 5397ec681f3Smrg * \param access bitmask of PIPE_MAP_x flags 540af69d88dSmrg */ 54101e04c3fSmrgstatic inline void * 5427ec681f3Smrgpipe_texture_map(struct pipe_context *context, 5437ec681f3Smrg struct pipe_resource *resource, 5447ec681f3Smrg unsigned level, unsigned layer, 5457ec681f3Smrg unsigned access, 5467ec681f3Smrg unsigned x, unsigned y, 5477ec681f3Smrg unsigned w, unsigned h, 5487ec681f3Smrg struct pipe_transfer **transfer) 5493464ebd5Sriastradh{ 5503464ebd5Sriastradh struct pipe_box box; 551af69d88dSmrg u_box_2d_zslice(x, y, layer, w, h, &box); 5527ec681f3Smrg return context->texture_map(context, resource, level, access, 5537ec681f3Smrg &box, transfer); 554cdc920a0Smrg} 555cdc920a0Smrg 556af69d88dSmrg 557af69d88dSmrg/** 558af69d88dSmrg * Map a 3D (texture) resource for reading/writing. 5597ec681f3Smrg * \param access bitmask of PIPE_MAP_x flags 560af69d88dSmrg */ 56101e04c3fSmrgstatic inline void * 5627ec681f3Smrgpipe_texture_map_3d(struct pipe_context *context, 5637ec681f3Smrg struct pipe_resource *resource, 5647ec681f3Smrg unsigned level, 5657ec681f3Smrg unsigned access, 5667ec681f3Smrg unsigned x, unsigned y, unsigned z, 5677ec681f3Smrg unsigned w, unsigned h, unsigned d, 5687ec681f3Smrg struct pipe_transfer **transfer) 569cdc920a0Smrg{ 570af69d88dSmrg struct pipe_box box; 571af69d88dSmrg u_box_3d(x, y, z, w, h, d, &box); 5727ec681f3Smrg return context->texture_map(context, resource, level, access, 5737ec681f3Smrg &box, transfer); 574cdc920a0Smrg} 575cdc920a0Smrg 57601e04c3fSmrgstatic inline void 5777ec681f3Smrgpipe_texture_unmap(struct pipe_context *context, 5787ec681f3Smrg struct pipe_transfer *transfer) 579cdc920a0Smrg{ 5807ec681f3Smrg context->texture_unmap(context, transfer); 581cdc920a0Smrg} 582cdc920a0Smrg 58301e04c3fSmrgstatic inline void 58401e04c3fSmrgpipe_set_constant_buffer(struct pipe_context *pipe, 58501e04c3fSmrg enum pipe_shader_type shader, uint index, 586af69d88dSmrg struct pipe_resource *buf) 587cdc920a0Smrg{ 588af69d88dSmrg if (buf) { 589af69d88dSmrg struct pipe_constant_buffer cb; 590af69d88dSmrg cb.buffer = buf; 591af69d88dSmrg cb.buffer_offset = 0; 592af69d88dSmrg cb.buffer_size = buf->width0; 593af69d88dSmrg cb.user_buffer = NULL; 5947ec681f3Smrg pipe->set_constant_buffer(pipe, shader, index, false, &cb); 595af69d88dSmrg } else { 5967ec681f3Smrg pipe->set_constant_buffer(pipe, shader, index, false, NULL); 597af69d88dSmrg } 598cdc920a0Smrg} 599cdc920a0Smrg 6003464ebd5Sriastradh 601af69d88dSmrg/** 602af69d88dSmrg * Get the polygon offset enable/disable flag for the given polygon fill mode. 603af69d88dSmrg * \param fill_mode one of PIPE_POLYGON_MODE_POINT/LINE/FILL 604af69d88dSmrg */ 60501e04c3fSmrgstatic inline boolean 606af69d88dSmrgutil_get_offset(const struct pipe_rasterizer_state *templ, 607af69d88dSmrg unsigned fill_mode) 608cdc920a0Smrg{ 6093464ebd5Sriastradh switch(fill_mode) { 6103464ebd5Sriastradh case PIPE_POLYGON_MODE_POINT: 6113464ebd5Sriastradh return templ->offset_point; 6123464ebd5Sriastradh case PIPE_POLYGON_MODE_LINE: 6133464ebd5Sriastradh return templ->offset_line; 6143464ebd5Sriastradh case PIPE_POLYGON_MODE_FILL: 6153464ebd5Sriastradh return templ->offset_tri; 616cdc920a0Smrg default: 6173464ebd5Sriastradh assert(0); 6183464ebd5Sriastradh return FALSE; 619cdc920a0Smrg } 620cdc920a0Smrg} 621cdc920a0Smrg 62201e04c3fSmrgstatic inline float 623af69d88dSmrgutil_get_min_point_size(const struct pipe_rasterizer_state *state) 624af69d88dSmrg{ 625af69d88dSmrg /* The point size should be clamped to this value at the rasterizer stage. 626af69d88dSmrg */ 627af69d88dSmrg return !state->point_quad_rasterization && 628af69d88dSmrg !state->point_smooth && 629af69d88dSmrg !state->multisample ? 1.0f : 0.0f; 630af69d88dSmrg} 631af69d88dSmrg 63201e04c3fSmrgstatic inline void 633af69d88dSmrgutil_query_clear_result(union pipe_query_result *result, unsigned type) 634af69d88dSmrg{ 635af69d88dSmrg switch (type) { 636af69d88dSmrg case PIPE_QUERY_OCCLUSION_PREDICATE: 63701e04c3fSmrg case PIPE_QUERY_OCCLUSION_PREDICATE_CONSERVATIVE: 638af69d88dSmrg case PIPE_QUERY_SO_OVERFLOW_PREDICATE: 63901e04c3fSmrg case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE: 640af69d88dSmrg case PIPE_QUERY_GPU_FINISHED: 641af69d88dSmrg result->b = FALSE; 642af69d88dSmrg break; 643af69d88dSmrg case PIPE_QUERY_OCCLUSION_COUNTER: 644af69d88dSmrg case PIPE_QUERY_TIMESTAMP: 645af69d88dSmrg case PIPE_QUERY_TIME_ELAPSED: 646af69d88dSmrg case PIPE_QUERY_PRIMITIVES_GENERATED: 647af69d88dSmrg case PIPE_QUERY_PRIMITIVES_EMITTED: 648af69d88dSmrg result->u64 = 0; 649af69d88dSmrg break; 650af69d88dSmrg case PIPE_QUERY_SO_STATISTICS: 651af69d88dSmrg memset(&result->so_statistics, 0, sizeof(result->so_statistics)); 652af69d88dSmrg break; 653af69d88dSmrg case PIPE_QUERY_TIMESTAMP_DISJOINT: 654af69d88dSmrg memset(&result->timestamp_disjoint, 0, sizeof(result->timestamp_disjoint)); 655af69d88dSmrg break; 656af69d88dSmrg case PIPE_QUERY_PIPELINE_STATISTICS: 657af69d88dSmrg memset(&result->pipeline_statistics, 0, sizeof(result->pipeline_statistics)); 658af69d88dSmrg break; 659af69d88dSmrg default: 660af69d88dSmrg memset(result, 0, sizeof(*result)); 661af69d88dSmrg } 662af69d88dSmrg} 663af69d88dSmrg 664af69d88dSmrg/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */ 66501e04c3fSmrgstatic inline enum tgsi_texture_type 666af69d88dSmrgutil_pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target, 667af69d88dSmrg unsigned nr_samples) 6683464ebd5Sriastradh{ 669af69d88dSmrg switch (pipe_tex_target) { 670af69d88dSmrg case PIPE_BUFFER: 671af69d88dSmrg return TGSI_TEXTURE_BUFFER; 672af69d88dSmrg 673af69d88dSmrg case PIPE_TEXTURE_1D: 674af69d88dSmrg assert(nr_samples <= 1); 675af69d88dSmrg return TGSI_TEXTURE_1D; 676af69d88dSmrg 677af69d88dSmrg case PIPE_TEXTURE_2D: 678af69d88dSmrg return nr_samples > 1 ? TGSI_TEXTURE_2D_MSAA : TGSI_TEXTURE_2D; 679af69d88dSmrg 680af69d88dSmrg case PIPE_TEXTURE_RECT: 681af69d88dSmrg assert(nr_samples <= 1); 682af69d88dSmrg return TGSI_TEXTURE_RECT; 683af69d88dSmrg 684af69d88dSmrg case PIPE_TEXTURE_3D: 685af69d88dSmrg assert(nr_samples <= 1); 686af69d88dSmrg return TGSI_TEXTURE_3D; 687af69d88dSmrg 688af69d88dSmrg case PIPE_TEXTURE_CUBE: 689af69d88dSmrg assert(nr_samples <= 1); 690af69d88dSmrg return TGSI_TEXTURE_CUBE; 691af69d88dSmrg 692af69d88dSmrg case PIPE_TEXTURE_1D_ARRAY: 693af69d88dSmrg assert(nr_samples <= 1); 694af69d88dSmrg return TGSI_TEXTURE_1D_ARRAY; 695af69d88dSmrg 696af69d88dSmrg case PIPE_TEXTURE_2D_ARRAY: 697af69d88dSmrg return nr_samples > 1 ? TGSI_TEXTURE_2D_ARRAY_MSAA : 698af69d88dSmrg TGSI_TEXTURE_2D_ARRAY; 699af69d88dSmrg 700af69d88dSmrg case PIPE_TEXTURE_CUBE_ARRAY: 701af69d88dSmrg return TGSI_TEXTURE_CUBE_ARRAY; 7023464ebd5Sriastradh 703af69d88dSmrg default: 704af69d88dSmrg assert(0 && "unexpected texture target"); 705af69d88dSmrg return TGSI_TEXTURE_UNKNOWN; 7063464ebd5Sriastradh } 707af69d88dSmrg} 708af69d88dSmrg 709af69d88dSmrg 71001e04c3fSmrgstatic inline void 711af69d88dSmrgutil_copy_constant_buffer(struct pipe_constant_buffer *dst, 7127ec681f3Smrg const struct pipe_constant_buffer *src, 7137ec681f3Smrg bool take_ownership) 714af69d88dSmrg{ 715af69d88dSmrg if (src) { 7167ec681f3Smrg if (take_ownership) { 7177ec681f3Smrg pipe_resource_reference(&dst->buffer, NULL); 7187ec681f3Smrg dst->buffer = src->buffer; 7197ec681f3Smrg } else { 7207ec681f3Smrg pipe_resource_reference(&dst->buffer, src->buffer); 7217ec681f3Smrg } 722af69d88dSmrg dst->buffer_offset = src->buffer_offset; 723af69d88dSmrg dst->buffer_size = src->buffer_size; 724af69d88dSmrg dst->user_buffer = src->user_buffer; 7253464ebd5Sriastradh } 726af69d88dSmrg else { 727af69d88dSmrg pipe_resource_reference(&dst->buffer, NULL); 728af69d88dSmrg dst->buffer_offset = 0; 729af69d88dSmrg dst->buffer_size = 0; 730af69d88dSmrg dst->user_buffer = NULL; 731af69d88dSmrg } 732af69d88dSmrg} 7333464ebd5Sriastradh 7347ec681f3Smrgstatic inline void 7357ec681f3Smrgutil_copy_shader_buffer(struct pipe_shader_buffer *dst, 7367ec681f3Smrg const struct pipe_shader_buffer *src) 7377ec681f3Smrg{ 7387ec681f3Smrg if (src) { 7397ec681f3Smrg pipe_resource_reference(&dst->buffer, src->buffer); 7407ec681f3Smrg dst->buffer_offset = src->buffer_offset; 7417ec681f3Smrg dst->buffer_size = src->buffer_size; 7427ec681f3Smrg } 7437ec681f3Smrg else { 7447ec681f3Smrg pipe_resource_reference(&dst->buffer, NULL); 7457ec681f3Smrg dst->buffer_offset = 0; 7467ec681f3Smrg dst->buffer_size = 0; 7477ec681f3Smrg } 7487ec681f3Smrg} 7497ec681f3Smrg 75001e04c3fSmrgstatic inline void 75101e04c3fSmrgutil_copy_image_view(struct pipe_image_view *dst, 75201e04c3fSmrg const struct pipe_image_view *src) 75301e04c3fSmrg{ 75401e04c3fSmrg if (src) { 75501e04c3fSmrg pipe_resource_reference(&dst->resource, src->resource); 75601e04c3fSmrg dst->format = src->format; 75701e04c3fSmrg dst->access = src->access; 758361fc4cbSmaya dst->shader_access = src->shader_access; 75901e04c3fSmrg dst->u = src->u; 76001e04c3fSmrg } else { 76101e04c3fSmrg pipe_resource_reference(&dst->resource, NULL); 76201e04c3fSmrg dst->format = PIPE_FORMAT_NONE; 76301e04c3fSmrg dst->access = 0; 764361fc4cbSmaya dst->shader_access = 0; 76501e04c3fSmrg memset(&dst->u, 0, sizeof(dst->u)); 76601e04c3fSmrg } 76701e04c3fSmrg} 76801e04c3fSmrg 76901e04c3fSmrgstatic inline unsigned 770af69d88dSmrgutil_max_layer(const struct pipe_resource *r, unsigned level) 771af69d88dSmrg{ 772af69d88dSmrg switch (r->target) { 773af69d88dSmrg case PIPE_TEXTURE_3D: 774af69d88dSmrg return u_minify(r->depth0, level) - 1; 77501e04c3fSmrg case PIPE_TEXTURE_CUBE: 77601e04c3fSmrg assert(r->array_size == 6); 7777ec681f3Smrg FALLTHROUGH; 778af69d88dSmrg case PIPE_TEXTURE_1D_ARRAY: 779af69d88dSmrg case PIPE_TEXTURE_2D_ARRAY: 780af69d88dSmrg case PIPE_TEXTURE_CUBE_ARRAY: 781af69d88dSmrg return r->array_size - 1; 782af69d88dSmrg default: 783af69d88dSmrg return 0; 784af69d88dSmrg } 7853464ebd5Sriastradh} 7863464ebd5Sriastradh 78701e04c3fSmrgstatic inline unsigned 78801e04c3fSmrgutil_num_layers(const struct pipe_resource *r, unsigned level) 78901e04c3fSmrg{ 79001e04c3fSmrg return util_max_layer(r, level) + 1; 79101e04c3fSmrg} 79201e04c3fSmrg 79301e04c3fSmrgstatic inline bool 79401e04c3fSmrgutil_texrange_covers_whole_level(const struct pipe_resource *tex, 79501e04c3fSmrg unsigned level, unsigned x, unsigned y, 79601e04c3fSmrg unsigned z, unsigned width, 79701e04c3fSmrg unsigned height, unsigned depth) 79801e04c3fSmrg{ 79901e04c3fSmrg return x == 0 && y == 0 && z == 0 && 80001e04c3fSmrg width == u_minify(tex->width0, level) && 80101e04c3fSmrg height == u_minify(tex->height0, level) && 80201e04c3fSmrg depth == util_num_layers(tex, level); 80301e04c3fSmrg} 80401e04c3fSmrg 8057ec681f3Smrg/** 8067ec681f3Smrg * Returns true if the blit will fully initialize all pixels in the resource. 8077ec681f3Smrg */ 8087ec681f3Smrgstatic inline bool 8097ec681f3Smrgutil_blit_covers_whole_resource(const struct pipe_blit_info *info) 8107ec681f3Smrg{ 8117ec681f3Smrg /* No conditional rendering or scissoring. (We assume that the caller would 8127ec681f3Smrg * have dropped any redundant scissoring) 8137ec681f3Smrg */ 8147ec681f3Smrg if (info->scissor_enable || info->window_rectangle_include || info->render_condition_enable || info->alpha_blend) 8157ec681f3Smrg return false; 8167ec681f3Smrg 8177ec681f3Smrg const struct pipe_resource *dst = info->dst.resource; 8187ec681f3Smrg /* A single blit can't initialize a miptree. */ 8197ec681f3Smrg if (dst->last_level != 0) 8207ec681f3Smrg return false; 8217ec681f3Smrg 8227ec681f3Smrg assert(info->dst.level == 0); 8237ec681f3Smrg 8247ec681f3Smrg /* Make sure the dst box covers the whole resource. */ 8257ec681f3Smrg if (!(util_texrange_covers_whole_level(dst, 0, 8267ec681f3Smrg 0, 0, 0, 8277ec681f3Smrg info->dst.box.width, info->dst.box.height, info->dst.box.depth))) { 8287ec681f3Smrg return false; 8297ec681f3Smrg } 8307ec681f3Smrg 8317ec681f3Smrg /* Make sure the mask actually updates all the channels present in the dst format. */ 8327ec681f3Smrg if (info->mask & PIPE_MASK_RGBA) { 8337ec681f3Smrg if ((info->mask & PIPE_MASK_RGBA) != PIPE_MASK_RGBA) 8347ec681f3Smrg return false; 8357ec681f3Smrg } 8367ec681f3Smrg 8377ec681f3Smrg if (info->mask & PIPE_MASK_ZS) { 8387ec681f3Smrg const struct util_format_description *format_desc = util_format_description(info->dst.format); 8397ec681f3Smrg uint32_t dst_has = 0; 8407ec681f3Smrg if (util_format_has_depth(format_desc)) 8417ec681f3Smrg dst_has |= PIPE_MASK_Z; 8427ec681f3Smrg if (util_format_has_stencil(format_desc)) 8437ec681f3Smrg dst_has |= PIPE_MASK_S; 8447ec681f3Smrg if (dst_has & ~(info->mask & PIPE_MASK_ZS)) 8457ec681f3Smrg return false; 8467ec681f3Smrg } 8477ec681f3Smrg 8487ec681f3Smrg return true; 8497ec681f3Smrg} 8507ec681f3Smrg 8517ec681f3Smrgstatic inline bool 8527ec681f3Smrgutil_logicop_reads_dest(enum pipe_logicop op) 8537ec681f3Smrg{ 8547ec681f3Smrg switch (op) { 8557ec681f3Smrg case PIPE_LOGICOP_NOR: 8567ec681f3Smrg case PIPE_LOGICOP_AND_INVERTED: 8577ec681f3Smrg case PIPE_LOGICOP_AND_REVERSE: 8587ec681f3Smrg case PIPE_LOGICOP_INVERT: 8597ec681f3Smrg case PIPE_LOGICOP_XOR: 8607ec681f3Smrg case PIPE_LOGICOP_NAND: 8617ec681f3Smrg case PIPE_LOGICOP_AND: 8627ec681f3Smrg case PIPE_LOGICOP_EQUIV: 8637ec681f3Smrg case PIPE_LOGICOP_NOOP: 8647ec681f3Smrg case PIPE_LOGICOP_OR_INVERTED: 8657ec681f3Smrg case PIPE_LOGICOP_OR_REVERSE: 8667ec681f3Smrg case PIPE_LOGICOP_OR: 8677ec681f3Smrg return true; 8687ec681f3Smrg case PIPE_LOGICOP_CLEAR: 8697ec681f3Smrg case PIPE_LOGICOP_COPY_INVERTED: 8707ec681f3Smrg case PIPE_LOGICOP_COPY: 8717ec681f3Smrg case PIPE_LOGICOP_SET: 8727ec681f3Smrg return false; 8737ec681f3Smrg } 8747ec681f3Smrg unreachable("bad logicop"); 8757ec681f3Smrg} 8767ec681f3Smrg 8777ec681f3Smrgstatic inline bool 8787ec681f3Smrgutil_writes_stencil(const struct pipe_stencil_state *s) 8797ec681f3Smrg{ 8807ec681f3Smrg return s->enabled && s->writemask && 8817ec681f3Smrg ((s->fail_op != PIPE_STENCIL_OP_KEEP) || 8827ec681f3Smrg (s->zpass_op != PIPE_STENCIL_OP_KEEP) || 8837ec681f3Smrg (s->zfail_op != PIPE_STENCIL_OP_KEEP)); 8847ec681f3Smrg} 8857ec681f3Smrg 8867ec681f3Smrgstatic inline bool 8877ec681f3Smrgutil_writes_depth_stencil(const struct pipe_depth_stencil_alpha_state *zsa) 8887ec681f3Smrg{ 8897ec681f3Smrg if (zsa->depth_enabled && zsa->depth_writemask && 8907ec681f3Smrg (zsa->depth_func != PIPE_FUNC_NEVER)) 8917ec681f3Smrg return true; 8927ec681f3Smrg 8937ec681f3Smrg return util_writes_stencil(&zsa->stencil[0]) || 8947ec681f3Smrg util_writes_stencil(&zsa->stencil[1]); 8957ec681f3Smrg} 8967ec681f3Smrg 8977ec681f3Smrgstatic inline struct pipe_context * 8987ec681f3Smrgpipe_create_multimedia_context(struct pipe_screen *screen) 8997ec681f3Smrg{ 9007ec681f3Smrg unsigned flags = 0; 9017ec681f3Smrg 9027ec681f3Smrg if (!screen->get_param(screen, PIPE_CAP_GRAPHICS)) 9037ec681f3Smrg flags |= PIPE_CONTEXT_COMPUTE_ONLY; 9047ec681f3Smrg 9057ec681f3Smrg return screen->context_create(screen, NULL, flags); 9067ec681f3Smrg} 9077ec681f3Smrg 9087ec681f3Smrgstatic inline unsigned util_res_sample_count(struct pipe_resource *res) 9097ec681f3Smrg{ 9107ec681f3Smrg return res->nr_samples > 0 ? res->nr_samples : 1; 9117ec681f3Smrg} 9127ec681f3Smrg 913cdc920a0Smrg#ifdef __cplusplus 914cdc920a0Smrg} 915cdc920a0Smrg#endif 916cdc920a0Smrg 917cdc920a0Smrg#endif /* U_INLINES_H */ 918