summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* r600g,radeonsi: share flags has_cp_dma and has_streamoutMarek Olšák2013-12-1210-26/+28
| | | | Reviewed-by: Michel Dänzer <[email protected]>
* radeonsi: handle PIPE_TRANSFER_DISCARD_WHOLE_RESOURCEMarek Olšák2013-12-123-0/+135
| | | | | | which can come from glBufferData and glMapBufferRange. Reviewed-by: Michel Dänzer <[email protected]>
* radeonsi: implement accelerated buffer copyingMarek Olšák2013-12-123-4/+64
| | | | Reviewed-by: Michel Dänzer <[email protected]>
* r600g: use common interfaces in buffer_transfer_unmapMarek Olšák2013-12-125-14/+22
| | | | | | i.e. dma_copy and resource_copy_region. Reviewed-by: Michel Dänzer <[email protected]>
* radeon: move some functions to r600_buffer_common.cMarek Olšák2013-12-124-130/+161
| | | | | | | | Reviewed-by: Michel Dänzer <[email protected]> Reviewed-by: Christoph Brill <[email protected]> v2: Renamed r600_buffer.c to r600_buffer_common.c. The stupid build system doesn't allow 2 files of the same name in different directories.
* winsys/radeon: set/get the scanout flag with the tiling ioctlsMarek Olšák2013-12-125-11/+22
| | | | | | | | | | | | | | | If we assume that all buffers allocated by the DDX are scanout, a new flag that says "this is not scanout" has to be added to support the non-scanout buffers and maintain backward compatibility. This fixes bad rendering on Wayland. The flag is defined as: #define RADEON_TILING_R600_NO_SCANOUT RADEON_TILING_SWAP_16BIT AFAIK, RADEON_TILING_SWAP_16BIT is not used on SI. Reviewed-by: Michel Dänzer <[email protected]>
* glsl: modify ir_clone to use memcpyTapani Pälli2013-12-121-20/+3
| | | | | | | | Patch copies the whole data structure at once instead of assigning individual variables. Signed-off-by: Tapani Pälli <[email protected]> Reviewed-by: Paul Berry <[email protected]>
* glsl: move variables in to ir_variable::data, part IITapani Pälli2013-12-1231-411/+421
| | | | | | | | | | | | | This patch moves following bitfields and variables to the data structure: explicit_location, explicit_index, explicit_binding, has_initializer, is_unmatched_generic_inout, location_frac, from_named_ifc_block_nonarray, from_named_ifc_block_array, depth_layout, location, index, binding, max_array_access, atomic Signed-off-by: Tapani Pälli <[email protected]> Reviewed-by: Paul Berry <[email protected]>
* glsl: move variables in to ir_variable::data, part ITapani Pälli2013-12-1246-307/+308
| | | | | | | | | | This patch moves following bitfields in to the data structure: used, assigned, how_declared, mode, interpolation, origin_upper_left, pixel_center_integer Signed-off-by: Tapani Pälli <[email protected]> Reviewed-by: Paul Berry <[email protected]>
* glsl: introduce data section to ir_variableTapani Pälli2013-12-1218-75/+83
| | | | | | | | Data section helps serialization and cloning of a ir_variable. This patch includes the helper bits used for read only ir_variables. Signed-off-by: Tapani Pälli <[email protected]> Reviewed-by: Paul Berry <[email protected]>
* mesa: fix a typo in glDetachShader error messageTapani Pälli2013-12-121-1/+1
| | | | | Signed-off-by: Tapani Pälli <[email protected]> Reviewed-by: Brian Paul <[email protected]>
* svga: expose HW smooth/stipple/wide linesBrian Paul2013-12-117-14/+99
| | | | | | | Newer virtual HW versions support smooth/stipple/wide lines. Use that instead of 'draw' fallbacks when possible. Reviewed-by: José Fonseca <[email protected]>
* glx: Add missing null check in DRI2WireToEventJuha-Pekka Heikkila2013-12-111-0/+2
| | | | | Signed-off-by: Juha-Pekka Heikkila <[email protected]> Reviewed-by: Brian Paul <[email protected]>
* llvmpipe: add plumbing for ARB_depth_clampMatthew McClure2013-12-114-35/+62
| | | | | | | | | | With this patch llvmpipe will adhere to the ARB_depth_clamp enabled state when clamping the fragment's zw value. To support this, the variant key now includes the depth_clamp state. key->depth_clamp is derived from pipe_rasterizer_state's (depth_clip == 0), thus depth clamp is only enabled when depth clip is disabled. Reviewed-by: Roland Scheidegger <[email protected]> Reviewed-by: José Fonseca <[email protected]>
* r600g/sb: fix stack size computation on evergreenVadim Girlin2013-12-111-4/+12
| | | | | | | | | | | | | | | | On evergreen we have to reserve 1 stack element in some additional cases besides the ones mentioned in the docs, but stack size computation was recently reimplemented exactly as described in the docs by the patch that added workarounds for stack issues on EG/CM, resulting in regressions with some apps (Serious Sam 3). This patch fixes it by restoring previous behavior. Fixes https://bugs.freedesktop.org/show_bug.cgi?id=72369 Signed-off-by: Vadim Girlin <[email protected]> Cc: "10.0" <[email protected]> Tested-by: Andre Heider <[email protected]>
* llvmpipe: add a very useful (disabled) debugging outputZack Rusin2013-12-101-0/+20
| | | | | | | | Disabled by default, but it's very useful when needed. Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: José Fonseca <[email protected]> Reviewed-by: Roland Scheidegger <[email protected]>
* draw: fix vbuf caching of vertices with inject front faceZack Rusin2013-12-101-0/+1
| | | | | | | | | | | | | | | Caching in the vbuf module meant that once a vertex has been emitted it was cached, but it's possible for a vertex at the same location to be emitted again, but this time with a different front-face semantic. Caching was causing the first version of the vertex to be emitted, which resulted in the renderer getting incorrect front-face attributes. By reseting the vertex_id (which is used for caching) we make sure that once a front-face info has been injected the vertex will endup getting emitted. Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: José Fonseca <[email protected]> Reviewed-by: Roland Scheidegger <[email protected]>
* llvmpipe: fix blending with half-float formatsZack Rusin2013-12-103-5/+108
| | | | | | | | | | | | | The fact that we flush denorms to zero breaks our half-float conversion and blending. This patches enables denorms for blending. It's a little tricky due to the llvm bug that makes it incorrectly reorder the mxcsr intrinsics: http://llvm.org/bugs/show_bug.cgi?id=6393 Signed-off-by: Zack Rusin <[email protected]> Reviewed-by: José Fonseca <[email protected]> Reviewed-by: Roland Scheidegger <[email protected]> Signed-off-by: Zack Rusin <[email protected]>
* svga/winsys: Implement surface sharing using prime fd handlesThomas Hellstrom2013-12-102-18/+74
| | | | | | | | | | This needs a prime-aware vmwgfx kernel module to work properly. (With additions by Christopher James Halse Rogers <[email protected]>) Signed-off-by: Christopher James Halse Rogers <[email protected]> Signed-off-by: Thomas Hellstrom <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* gallium/radeon: Implement hooks for DRI Image 7 (v2)Christopher James Halse Rogers2013-12-104-24/+141
| | | | | | | | | v2: Fix transliteration of lseek arguments Ignore busy return from RADEON_GEM_BUSY ioctl; we're only after the domain Signed-off-by: Christopher James Halse Rogers <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* radeon: Rename bo_handles hashtable to match its actual contents.Christopher James Halse Rogers2013-12-101-8/+8
| | | | | | | | It's a map of GEM name->bo, so identify it as such Signed-off-by: Christopher James Halse Rogers <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* ilo: Support DRI Image 7Christopher James Halse Rogers2013-12-102-3/+18
| | | | | | Signed-off-by: Christopher James Halse Rogers <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* nouveau: Support DRI Image 7 extensionMaarten Lankhorst2013-12-102-3/+26
| | | | | | Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Christopher James Halse Rogers <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* gallium/dri: Support DRI Image extension version 7Christopher James Halse Rogers2013-12-102-10/+106
| | | | | | | | | | | v2: Fix up queryImage return for ATTRIB_FD Use driver_descriptor.configuration to determine whether the driver supports DMA-BUF import/export. v3: Really, truly, fix up queryImage return for ATTRIB_FD Signed-off-by: Christopher James Halse Rogers <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* gallium/dri2: Set winsys_handle type to KMS for stride query.Christopher James Halse Rogers2013-12-101-0/+1
| | | | | | | | | Otherwise the default is TYPE_SHARED, which will flink the bo. This seems rather unnecessary for a simple stride query. Signed-off-by: Christopher James Halse Rogers <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* gallium/winsys/drm: Prepare for passing prime fds in winsys_handleChristopher James Halse Rogers2013-12-109-4/+38
| | | | | | Signed-off-by: Christopher James Halse Rogers <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* gallium/dri: Support DRI Image extension version 6Christopher James Halse Rogers2013-12-101-1/+71
| | | | | | | | | | v2: Pick out the correct gl_context pointer v3: Don't leak pipe_resources on error path Set img->dri_format correctly Signed-off-by: Christopher James Halse Rogers <[email protected]> Reviewed-by: Thomas Hellstrom <[email protected]> Signed-off-by: Maarten Lankhorst <[email protected]>
* nv50: report 15 max inputs for fragment programsIlia Mirkin2013-12-101-1/+1
| | | | | | | | | | | | First off, nv50_program only has 16 in/out varyings. However reporting 16 makes 'm' become 68 in nv50_fp_linkage_validate with the varying-packing-simple piglit test. (Subverting the assert makes it compile but fail.) With this patch, varying-packing-simple passes. See: https://bugs.freedesktop.org/show_bug.cgi?id=69155 Signed-off-by: Ilia Mirkin <[email protected]> Cc: "9.2 10.0" <[email protected]>
* nouveau: Fix compiler warning regressionMaarten Lankhorst2013-12-101-4/+0
| | | | | | cfg is now unused, remove it. Cc: "10.0" <[email protected]>
* swrast: fix readback regression since inversion fixDave Airlie2013-12-101-1/+1
| | | | | | | | | | | | | | | This readback from the frontbuffer with swrast was broken, that bug just made it more obviously broken, this fixes it by inverting the sub image gets. Also fixes a few other piglits. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=72327 Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=72325 (for 9.2 the patches this depends on were asked to be backported separately in an email). Cc: "9.2" "10.0" [email protected] Reviewed-by: Brian Paul <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
* dri megadriver_stub: add compatibility for older DRI loadersJordan Justen2013-12-091-0/+126
| | | | | | | | | | | | | | | | | | To help the transition period when DRI loaders are being updated to support the newer __driDriverExtensions_foo mechanism, we populate __driDriverExtensions with the extensions returned by __driDriverExtensions_foo during a library contructor function. We find the driver foo's name by using the dladdr function which gives the path of the dynamic library's name that was being loaded. Signed-off-by: Jordan Justen <[email protected]> Reviewed-by: Matt Turner <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]> Reviewed-by: Keith Packard <[email protected]> Cc: "10.0" <[email protected]>
* egl/wayland: Return -1 from get_back_bo to indicate errorKristian Høgsberg2013-12-091-1/+1
| | | | | A return value of -1 indicate failure to allocate the back buffer and means we don't segfault on the way out.
* egl_dri2: Remove the unused swap_interval member of dri2_egl_surfaceNeil Roberts2013-12-091-1/+0
| | | | | | The _EGLSurface struct which is embedded into dri2_egl_surface also contains a swap interval member so the other member is redundant. Nothing was using it as far as I can tell.
* i965: Replace OUT_RELOC_FENCED with OUT_RELOC.Kenneth Graunke2013-12-092-16/+10
| | | | | | | | | | | | | | On Gen4+, OUT_RELOC_FENCED is equivalent to OUT_RELOC; libdrm silently ignores the fenced flag: /* We never use HW fences for rendering on 965+ */ if (bufmgr_gem->gen >= 4) need_fence = false; Thanks to Eric for noticing this. Signed-off-by: Kenneth Graunke <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
* glsl/loops: Get rid of lower_bounded_loops and ir_loop::normative_bound.Paul Berry2013-12-0945-221/+35
| | | | | | | | Now that loop_controls no longer creates normatively bound loops, there is no need for ir_loop::normative_bound or the lower_bounded_loops pass. Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: Stop creating normatively bound loops in loop_controls.Paul Berry2013-12-093-20/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, when loop_controls analyzed a loop and found that it had a fixed bound (known at compile time), it would remove all of the loop terminators and instead set the loop's normative_bound field to force the loop to execute the correct number of times. This made loop unrolling easy, but it had a serious disadvantage. Since most GPU's don't have a native mechanism for executing a loop a fixed number of times, in order to implement the normative bound, the back-ends would have to synthesize a new loop induction variable. As a result, many loops wound up having two induction variables instead of one. This caused extra register pressure and unnecessary instructions. This patch modifies loop_controls so that it doesn't set the loop's normative_bound anymore. Instead it leaves one of the terminators in the loop (the limiting terminator), so the back-end doesn't have to go to any extra work to ensure the loop terminates at the right time. This complicates loop unrolling slightly: when deciding whether a loop can be unrolled, we have to account for the presence of the limiting terminator. And when we do unroll the loop, we have to remove the limiting terminator first. For an example of how this results in more efficient back end code, consider the loop: for (int i = 0; i < 100; i++) { total += i; } Previous to this patch, on i965, this loop would compile down to this (vec4) native code: mov(8) g4<1>.xD 0D mov(8) g8<1>.xD 0D loop: cmp.ge.f0(8) null g8<4;4,1>.xD 100D (+f0) if(8) break(8) endif(8) add(8) g5<1>.xD g5<4;4,1>.xD g4<4;4,1>.xD add(8) g8<1>.xD g8<4;4,1>.xD 1D add(8) g4<1>.xD g4<4;4,1>.xD 1D while(8) loop (notice that both g8 and g4 are loop induction variables; one is used to terminate the loop, and the other is used to accumulate the total). After this patch, the same loop compiles to: mov(8) g4<1>.xD 0D loop: cmp.ge.f0(8) null g4<4;4,1>.xD 100D (+f0) if(8) break(8) endif(8) add(8) g5<1>.xD g5<4;4,1>.xD g4<4;4,1>.xD add(8) g4<1>.xD g4<4;4,1>.xD 1D while(8) loop Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: Get rid of loop_variable_state::max_iterations.Paul Berry2013-12-093-38/+19
| | | | | | | | This value is now redundant with loop_variable_state::limiting_terminator->iterations and ir_loop::normative_bound. Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: Simplify loop unrolling logic by breaking into functions.Paul Berry2013-12-091-108/+184
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The old logic of loop_unroll_visitor::visit_leave(ir_loop *) was: heuristics to skip unrolling in various circumstances; if (loop contains more than one jump) return; else if (loop contains one jump) { if (the jump is an unconditional "break" at the end of the loop) { remove the break and set iteration count to 1; fall through to simple loop unrolling code; } else { for (each "if" statement in the loop body) see if the jump is a "break" at the end of one of its forks; if (the "break" wasn't found) return; splice the remainder of the loop into the other fork of the "if"; remove the "break"; complex loop unrolling code; return; } } simple loop unrolling code; return; These tasks have been moved to their own functions: - splice the remainder of the loop into the other fork of the "if" - simple loop unrolling code - complex loop unrolling code And the logic has been flattened to: heuristics to skip unrolling in various circumstances; if (loop contains more than one jump) return; if (loop contains no jumps) { simple loop unroll; return; } if (the jump is an unconditional "break" at the end of the loop) { remove the break; simple loop unroll with iteration count of 1; return; } for (each "if" statement in the loop body) { if (the jump is a "break" at the end of one of its forks) { splice the remainder of the loop into the other fork of the "if"; remove the "break"; complex loop unroll; return; } } This will make it easier to modify the loop unrolling algorithm in a future patch. Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: Move some analysis from loop_controls to loop_analysis.Paul Berry2013-12-093-80/+125
| | | | | | | | | | | | | | | | | | | | Previously, the sole responsibility of loop_analysis was to find all the variables referenced in the loop that are either loop constant or induction variables, and find all of the simple if statements that might terminate the loop. The remainder of the analysis necessary to determine how many times a loop executed was performed by loop_controls. This patch makes loop_analysis also responsible for determining the number of iterations after which each loop terminator will terminate the loop, and for figuring out which terminator will terminate the loop first (I'm calling this the "limiting terminator"). This will allow loop unrolling to make use of information that was previously only visible from loop_controls, namely the identity of the limiting terminator. Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: Allocate loop_terminator using new(mem_ctx) syntax.Paul Berry2013-12-091-1/+1
| | | | | | | | Patches to follow will introduce code into the loop_terminator constructor. Allocating loop_terminator using new(mem_ctx) syntax will ensure that the constructor runs. Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: Remove unnecessary list walk from loop_control_visitor.Paul Berry2013-12-092-33/+39
| | | | | | | | | | | When loop_control_visitor::visit_leave(ir_loop *) is analyzing a loop terminator that acts on a certain ir_variable, it doesn't need to walk the list of induction variables to find the loop_variable entry corresponding to the variable. It can just look it up in the loop_variable_state hashtable and verify that the loop_variable entry represents an induction variable. Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: Remove unused fields iv_scale and biv from loop_variable class.Paul Berry2013-12-092-12/+4
| | | | | | | | | These fields were part of some planned optimizations that never materialized. Remove them for now to simplify things; if we ever get round to adding the optimizations that would require them, we can always re-introduce them. Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: replace loop controls with a normative bound.Paul Berry2013-12-0946-247/+104
| | | | | | | | | | | | | | This patch replaces the ir_loop fields "from", "to", "increment", "counter", and "cmp" with a single integer ("normative_bound") that serves the same purpose. I've used the name "normative_bound" to emphasize the fact that the back-end is required to emit code to prevent the loop from running more than normative_bound times. (By contrast, an "informative" bound would be a bound that is informational only). Reviewed-by: Jordan Justen <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glsl/loops: consolidate bounded loop handling into a lowering pass.Paul Berry2013-12-098-143/+133
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, all of the back-ends (ir_to_mesa, st_glsl_to_tgsi, and the i965 fs and vec4 visitors) had nearly identical logic for handling bounded loops. This replaces the duplicate logic with an equivalent lowering pass that is used by all the back-ends. Note: on i965, there is a slight increase in instruction count. For example, a loop like this: for (int i = 0; i < 100; i++) { total += i; } would previously compile down to this (vec4) native code: mov(8) g4<1>.xD 0D mov(8) g8<1>.xD 0D loop: cmp.ge.f0(8) null g8<4;4,1>.xD 100D (+f0) break(8) add(8) g5<1>.xD g5<4;4,1>.xD g4<4;4,1>.xD add(8) g8<1>.xD g8<4;4,1>.xD 1D add(8) g4<1>.xD g4<4;4,1>.xD 1D while(8) loop After this patch, the "(+f0) break(8)" turns into: (+f0) if(8) break(8) endif(8) because the back-end isn't smart enough to recognize that "if (condition) break;" can be done using a conditional break instruction. However, it should be relatively easy for a future peephole optimization to properly optimize this. Reviewed-by: Jordan Justen <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glsl: In loop analysis, handle unconditional second assignment.Paul Berry2013-12-091-3/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, loop analysis would set this->conditional_or_nested_assignment based on the most recently visited assignment to the variable. As a result, if a vaiable was assigned to more than once in a loop, the flag might be set incorrectly. For example, in a loop like this: int x; for (int i = 0; i < 3; i++) { if (i == 0) x = 10; ... x = 20; ... } loop analysis would have incorrectly concluded that all assignments to x were unconditional. In practice this was a benign bug, because conditional_or_nested_assignment is only used to disqualify variables from being considered as loop induction variables or loop constant variables, and having multiple assignments also disqualifies a variable from being considered as either of those things. Still, we should get the analysis correct to avoid future confusion. Reviewed-by: Jordan Justen <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glsl: Fix handling of function calls inside nested loops.Paul Berry2013-12-091-7/+7
| | | | | | | | | | | | | | | | | | | | | Previously, when visiting an ir_call, loop analysis would only mark the innermost enclosing loop as containing a call. As a result, when encountering a loop like this: for (i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { foo(); } } it would incorrectly conclude that the outer loop ran three times. (This is not certain; if foo() modifies i, then the outer loop might run more or fewer times). Fixes piglit test "vs-call-in-nested-loop.shader_test". Reviewed-by: Jordan Justen <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glsl: Fix loop analysis of nested loops.Paul Berry2013-12-092-17/+29
| | | | | | | | | | | | | | | | | | | | Previously, when visiting a variable dereference, loop analysis would only consider its effect on the innermost enclosing loop. As a result, when encountering a loop like this: for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { ... i = 2; } } it would incorrectly conclude that the outer loop ran three times. Fixes piglit test "vs-inner-loop-modifies-outer-loop-var.shader_test". Reviewed-by: Jordan Justen <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* glsl: Extract functions from loop_analysis::visit(ir_dereference_variable *).Paul Berry2013-12-092-25/+71
| | | | | | | This function is about to get more complex. Reviewed-by: Jordan Justen <[email protected]> Reviewed-by: Ian Romanick <[email protected]>
* i965/gen7+: Implement fast color clears for MSAA buffers.Paul Berry2013-12-091-44/+87
| | | | | | | | | | Fast color clears of MSAA buffers work just like fast color clears with non-MSAA buffers, except that the alignment and scaledown requirements are different. Reviewed-by: Kenneth Graunke <[email protected]> Reviewed-by: Chad Versace <[email protected]> Reviewed-by: Anuj Phogat <[email protected]>
* i965/blorp: Refactor code for computing fast clear align/scaledown factors.Paul Berry2013-12-091-19/+23
| | | | | | | | | This will make it easier to add fast color clear support to MSAA buffers, since they have different alignment and scaling requirements. Reviewed-by: Chad Versace <[email protected]> Reviewed-by: Anuj Phogat <[email protected]> Reviewed-by: Kenneth Graunke <[email protected]>