1bf215546Sopenharmony_ci/**********************************************************
2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person
5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation
6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without
7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy,
8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies
9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is
10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be
13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci **********************************************************/
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include "svga_cmd.h"
27bf215546Sopenharmony_ci#include "svga_debug.h"
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "pipe/p_defines.h"
30bf215546Sopenharmony_ci#include "util/u_pack_color.h"
31bf215546Sopenharmony_ci#include "util/u_surface.h"
32bf215546Sopenharmony_ci
33bf215546Sopenharmony_ci#include "svga_context.h"
34bf215546Sopenharmony_ci#include "svga_state.h"
35bf215546Sopenharmony_ci#include "svga_surface.h"
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci/**
39bf215546Sopenharmony_ci * Saving blitter states before doing any blitter operation
40bf215546Sopenharmony_ci */
41bf215546Sopenharmony_cistatic void
42bf215546Sopenharmony_cibegin_blit(struct svga_context *svga)
43bf215546Sopenharmony_ci{
44bf215546Sopenharmony_ci   util_blitter_save_vertex_buffer_slot(svga->blitter, svga->curr.vb);
45bf215546Sopenharmony_ci   util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
46bf215546Sopenharmony_ci   util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
47bf215546Sopenharmony_ci   util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);
48bf215546Sopenharmony_ci   util_blitter_save_tessctrl_shader(svga->blitter, svga->curr.tcs);
49bf215546Sopenharmony_ci   util_blitter_save_tesseval_shader(svga->blitter, svga->curr.tes);
50bf215546Sopenharmony_ci   util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
51bf215546Sopenharmony_ci                     (struct pipe_stream_output_target**)svga->so_targets);
52bf215546Sopenharmony_ci   util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
53bf215546Sopenharmony_ci   util_blitter_save_viewport(svga->blitter, &svga->curr.viewport[0]);
54bf215546Sopenharmony_ci   util_blitter_save_scissor(svga->blitter, &svga->curr.scissor[0]);
55bf215546Sopenharmony_ci   util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);
56bf215546Sopenharmony_ci   util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);
57bf215546Sopenharmony_ci   util_blitter_save_depth_stencil_alpha(svga->blitter,
58bf215546Sopenharmony_ci                                         (void*)svga->curr.depth);
59bf215546Sopenharmony_ci   util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref);
60bf215546Sopenharmony_ci   util_blitter_save_sample_mask(svga->blitter, svga->curr.sample_mask, 0);
61bf215546Sopenharmony_ci   util_blitter_save_fragment_constant_buffer_slot(svga->blitter,
62bf215546Sopenharmony_ci                                                   &svga->curr.constbufs[PIPE_SHADER_FRAGMENT][0]);
63bf215546Sopenharmony_ci}
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci/**
67bf215546Sopenharmony_ci * Clear the whole color buffer(s) by drawing a quad.  For VGPU10 we use
68bf215546Sopenharmony_ci * this when clearing integer render targets.  We'll also clear the
69bf215546Sopenharmony_ci * depth and/or stencil buffers if the clear_buffers mask specifies them.
70bf215546Sopenharmony_ci */
71bf215546Sopenharmony_cistatic void
72bf215546Sopenharmony_ciclear_buffers_with_quad(struct svga_context *svga,
73bf215546Sopenharmony_ci                        unsigned clear_buffers,
74bf215546Sopenharmony_ci                        const union pipe_color_union *color,
75bf215546Sopenharmony_ci                        double depth, unsigned stencil)
76bf215546Sopenharmony_ci{
77bf215546Sopenharmony_ci   const struct pipe_framebuffer_state *fb = &svga->curr.framebuffer;
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci   begin_blit(svga);
80bf215546Sopenharmony_ci   util_blitter_clear(svga->blitter,
81bf215546Sopenharmony_ci                      fb->width, fb->height,
82bf215546Sopenharmony_ci                      1, /* num_layers */
83bf215546Sopenharmony_ci                      clear_buffers, color,
84bf215546Sopenharmony_ci                      depth, stencil,
85bf215546Sopenharmony_ci                      util_framebuffer_get_num_samples(fb) > 1);
86bf215546Sopenharmony_ci}
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci/**
90bf215546Sopenharmony_ci * Check if any of the color buffers are integer buffers.
91bf215546Sopenharmony_ci */
92bf215546Sopenharmony_cistatic boolean
93bf215546Sopenharmony_ciis_integer_target(struct pipe_framebuffer_state *fb, unsigned buffers)
94bf215546Sopenharmony_ci{
95bf215546Sopenharmony_ci   unsigned i;
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci   for (i = 0; i < fb->nr_cbufs; i++) {
98bf215546Sopenharmony_ci      if ((buffers & (PIPE_CLEAR_COLOR0 << i)) &&
99bf215546Sopenharmony_ci          fb->cbufs[i] &&
100bf215546Sopenharmony_ci          util_format_is_pure_integer(fb->cbufs[i]->format)) {
101bf215546Sopenharmony_ci         return TRUE;
102bf215546Sopenharmony_ci      }
103bf215546Sopenharmony_ci   }
104bf215546Sopenharmony_ci   return FALSE;
105bf215546Sopenharmony_ci}
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci/**
109bf215546Sopenharmony_ci * Check if the integer values in the clear color can be represented
110bf215546Sopenharmony_ci * by floats.  If so, we can use the VGPU10 ClearRenderTargetView command.
111bf215546Sopenharmony_ci * Otherwise, we need to clear with a quad.
112bf215546Sopenharmony_ci */
113bf215546Sopenharmony_cistatic boolean
114bf215546Sopenharmony_ciints_fit_in_floats(const union pipe_color_union *color)
115bf215546Sopenharmony_ci{
116bf215546Sopenharmony_ci   const int max = 1 << 24;
117bf215546Sopenharmony_ci   return (color->i[0] <= max &&
118bf215546Sopenharmony_ci           color->i[1] <= max &&
119bf215546Sopenharmony_ci           color->i[2] <= max &&
120bf215546Sopenharmony_ci           color->i[3] <= max);
121bf215546Sopenharmony_ci}
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_cistatic enum pipe_error
125bf215546Sopenharmony_citry_clear(struct svga_context *svga,
126bf215546Sopenharmony_ci          unsigned buffers,
127bf215546Sopenharmony_ci          const union pipe_color_union *color,
128bf215546Sopenharmony_ci          double depth,
129bf215546Sopenharmony_ci          unsigned stencil)
130bf215546Sopenharmony_ci{
131bf215546Sopenharmony_ci   enum pipe_error ret = PIPE_OK;
132bf215546Sopenharmony_ci   SVGA3dRect rect = { 0, 0, 0, 0 };
133bf215546Sopenharmony_ci   boolean restore_viewport = FALSE;
134bf215546Sopenharmony_ci   SVGA3dClearFlag flags = 0;
135bf215546Sopenharmony_ci   struct pipe_framebuffer_state *fb = &svga->curr.framebuffer;
136bf215546Sopenharmony_ci   union util_color uc = {0};
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   ret = svga_update_state(svga, SVGA_STATE_HW_CLEAR);
139bf215546Sopenharmony_ci   if (ret != PIPE_OK)
140bf215546Sopenharmony_ci      return ret;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   if (svga->rebind.flags.rendertargets) {
143bf215546Sopenharmony_ci      ret = svga_reemit_framebuffer_bindings(svga);
144bf215546Sopenharmony_ci      if (ret != PIPE_OK) {
145bf215546Sopenharmony_ci         return ret;
146bf215546Sopenharmony_ci      }
147bf215546Sopenharmony_ci   }
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   if (buffers & PIPE_CLEAR_COLOR) {
150bf215546Sopenharmony_ci      flags |= SVGA3D_CLEAR_COLOR;
151bf215546Sopenharmony_ci      util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci      rect.w = fb->width;
154bf215546Sopenharmony_ci      rect.h = fb->height;
155bf215546Sopenharmony_ci   }
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && fb->zsbuf) {
158bf215546Sopenharmony_ci      if (buffers & PIPE_CLEAR_DEPTH)
159bf215546Sopenharmony_ci         flags |= SVGA3D_CLEAR_DEPTH;
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci      if (buffers & PIPE_CLEAR_STENCIL)
162bf215546Sopenharmony_ci         flags |= SVGA3D_CLEAR_STENCIL;
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci      rect.w = MAX2(rect.w, fb->zsbuf->width);
165bf215546Sopenharmony_ci      rect.h = MAX2(rect.h, fb->zsbuf->height);
166bf215546Sopenharmony_ci   }
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   if (!svga_have_vgpu10(svga) &&
169bf215546Sopenharmony_ci       !svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) {
170bf215546Sopenharmony_ci      restore_viewport = TRUE;
171bf215546Sopenharmony_ci      ret = SVGA3D_SetViewport(svga->swc, &rect);
172bf215546Sopenharmony_ci      if (ret != PIPE_OK)
173bf215546Sopenharmony_ci         return ret;
174bf215546Sopenharmony_ci   }
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   if (svga_have_vgpu10(svga)) {
177bf215546Sopenharmony_ci      if (flags & SVGA3D_CLEAR_COLOR) {
178bf215546Sopenharmony_ci         unsigned i;
179bf215546Sopenharmony_ci         bool int_target = is_integer_target(fb, buffers);
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ci         if (int_target && !ints_fit_in_floats(color)) {
182bf215546Sopenharmony_ci            clear_buffers_with_quad(svga, buffers, color, depth, stencil);
183bf215546Sopenharmony_ci            /* We also cleared depth/stencil, so that's done */
184bf215546Sopenharmony_ci            flags &= ~(SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL);
185bf215546Sopenharmony_ci         }
186bf215546Sopenharmony_ci         else {
187bf215546Sopenharmony_ci            struct pipe_surface *rtv;
188bf215546Sopenharmony_ci            float rgba[4];
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci            if (int_target) {
191bf215546Sopenharmony_ci               rgba[0] = (float) color->i[0];
192bf215546Sopenharmony_ci               rgba[1] = (float) color->i[1];
193bf215546Sopenharmony_ci               rgba[2] = (float) color->i[2];
194bf215546Sopenharmony_ci               rgba[3] = (float) color->i[3];
195bf215546Sopenharmony_ci            }
196bf215546Sopenharmony_ci            else {
197bf215546Sopenharmony_ci               rgba[0] = color->f[0];
198bf215546Sopenharmony_ci               rgba[1] = color->f[1];
199bf215546Sopenharmony_ci               rgba[2] = color->f[2];
200bf215546Sopenharmony_ci               rgba[3] = color->f[3];
201bf215546Sopenharmony_ci            }
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci            /* Issue VGPU10 Clear commands */
204bf215546Sopenharmony_ci            for (i = 0; i < fb->nr_cbufs; i++) {
205bf215546Sopenharmony_ci               if ((fb->cbufs[i] == NULL) ||
206bf215546Sopenharmony_ci                   !(buffers & (PIPE_CLEAR_COLOR0 << i)))
207bf215546Sopenharmony_ci                  continue;
208bf215546Sopenharmony_ci
209bf215546Sopenharmony_ci               rtv = svga_validate_surface_view(svga,
210bf215546Sopenharmony_ci                                                svga_surface(fb->cbufs[i]));
211bf215546Sopenharmony_ci               if (!rtv)
212bf215546Sopenharmony_ci                  return PIPE_ERROR_OUT_OF_MEMORY;
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci               ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, rgba);
215bf215546Sopenharmony_ci               if (ret != PIPE_OK)
216bf215546Sopenharmony_ci                  return ret;
217bf215546Sopenharmony_ci            }
218bf215546Sopenharmony_ci         }
219bf215546Sopenharmony_ci      }
220bf215546Sopenharmony_ci      if (flags & (SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL)) {
221bf215546Sopenharmony_ci         struct pipe_surface *dsv =
222bf215546Sopenharmony_ci            svga_validate_surface_view(svga, svga_surface(fb->zsbuf));
223bf215546Sopenharmony_ci         if (!dsv)
224bf215546Sopenharmony_ci            return PIPE_ERROR_OUT_OF_MEMORY;
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci         ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, flags,
227bf215546Sopenharmony_ci                                                   stencil, (float) depth);
228bf215546Sopenharmony_ci         if (ret != PIPE_OK)
229bf215546Sopenharmony_ci            return ret;
230bf215546Sopenharmony_ci      }
231bf215546Sopenharmony_ci   }
232bf215546Sopenharmony_ci   else {
233bf215546Sopenharmony_ci      ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil,
234bf215546Sopenharmony_ci                             rect.x, rect.y, rect.w, rect.h);
235bf215546Sopenharmony_ci      if (ret != PIPE_OK)
236bf215546Sopenharmony_ci         return ret;
237bf215546Sopenharmony_ci   }
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci   if (restore_viewport) {
240bf215546Sopenharmony_ci      ret = SVGA3D_SetViewport(svga->swc, &svga->state.hw_clear.viewport);
241bf215546Sopenharmony_ci   }
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   return ret;
244bf215546Sopenharmony_ci}
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci/**
247bf215546Sopenharmony_ci * Clear the given surface to the specified value.
248bf215546Sopenharmony_ci * No masking, no scissor (clear entire buffer).
249bf215546Sopenharmony_ci */
250bf215546Sopenharmony_cistatic void
251bf215546Sopenharmony_cisvga_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
252bf215546Sopenharmony_ci           const union pipe_color_union *color,
253bf215546Sopenharmony_ci	   double depth, unsigned stencil)
254bf215546Sopenharmony_ci{
255bf215546Sopenharmony_ci   struct svga_context *svga = svga_context( pipe );
256bf215546Sopenharmony_ci   enum pipe_error ret;
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   if (buffers & PIPE_CLEAR_COLOR) {
259bf215546Sopenharmony_ci      struct svga_winsys_surface *h = NULL;
260bf215546Sopenharmony_ci      if (svga->curr.framebuffer.cbufs[0]) {
261bf215546Sopenharmony_ci         h = svga_surface(svga->curr.framebuffer.cbufs[0])->handle;
262bf215546Sopenharmony_ci      }
263bf215546Sopenharmony_ci      SVGA_DBG(DEBUG_DMA, "clear sid %p\n", h);
264bf215546Sopenharmony_ci   }
265bf215546Sopenharmony_ci
266bf215546Sopenharmony_ci   /* flush any queued prims (don't want them to appear after the clear!) */
267bf215546Sopenharmony_ci   svga_hwtnl_flush_retry(svga);
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci   SVGA_RETRY_OOM(svga, ret, try_clear( svga, buffers, color, depth, stencil));
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci   /*
272bf215546Sopenharmony_ci    * Mark target surfaces as dirty
273bf215546Sopenharmony_ci    * TODO Mark only cleared surfaces.
274bf215546Sopenharmony_ci    */
275bf215546Sopenharmony_ci   svga_mark_surfaces_dirty(svga);
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   assert (ret == PIPE_OK);
278bf215546Sopenharmony_ci}
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_cistatic void
282bf215546Sopenharmony_cisvga_clear_texture(struct pipe_context *pipe,
283bf215546Sopenharmony_ci                   struct pipe_resource *res,
284bf215546Sopenharmony_ci                   unsigned level,
285bf215546Sopenharmony_ci                   const struct pipe_box *box,
286bf215546Sopenharmony_ci                   const void *data)
287bf215546Sopenharmony_ci{
288bf215546Sopenharmony_ci   struct svga_context *svga = svga_context(pipe);
289bf215546Sopenharmony_ci   struct svga_surface *svga_surface_dst;
290bf215546Sopenharmony_ci   struct pipe_surface tmpl;
291bf215546Sopenharmony_ci   struct pipe_surface *surface;
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   memset(&tmpl, 0, sizeof(tmpl));
294bf215546Sopenharmony_ci   tmpl.format = res->format;
295bf215546Sopenharmony_ci   tmpl.u.tex.first_layer = box->z;
296bf215546Sopenharmony_ci   tmpl.u.tex.last_layer = box->z + box->depth - 1;
297bf215546Sopenharmony_ci   tmpl.u.tex.level = level;
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci   surface = pipe->create_surface(pipe, res, &tmpl);
300bf215546Sopenharmony_ci   if (surface == NULL) {
301bf215546Sopenharmony_ci      debug_printf("failed to create surface\n");
302bf215546Sopenharmony_ci      return;
303bf215546Sopenharmony_ci   }
304bf215546Sopenharmony_ci   svga_surface_dst = svga_surface(surface);
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci   union pipe_color_union color;
307bf215546Sopenharmony_ci   const struct util_format_description *desc =
308bf215546Sopenharmony_ci      util_format_description(surface->format);
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci   if (util_format_is_depth_or_stencil(surface->format)) {
311bf215546Sopenharmony_ci      float depth;
312bf215546Sopenharmony_ci      uint8_t stencil;
313bf215546Sopenharmony_ci      unsigned clear_flags = 0;
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci      /* If data is NULL, then set depthValue and stencilValue to zeros */
316bf215546Sopenharmony_ci      if (data == NULL) {
317bf215546Sopenharmony_ci         depth = 0.0;
318bf215546Sopenharmony_ci         stencil = 0;
319bf215546Sopenharmony_ci      }
320bf215546Sopenharmony_ci      else {
321bf215546Sopenharmony_ci         util_format_unpack_z_float(surface->format, &depth, data, 1);
322bf215546Sopenharmony_ci         util_format_unpack_s_8uint(surface->format, &stencil, data, 1);
323bf215546Sopenharmony_ci      }
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci      if (util_format_has_depth(desc)) {
326bf215546Sopenharmony_ci         clear_flags |= PIPE_CLEAR_DEPTH;
327bf215546Sopenharmony_ci      }
328bf215546Sopenharmony_ci      if (util_format_has_stencil(desc)) {
329bf215546Sopenharmony_ci         clear_flags |= PIPE_CLEAR_STENCIL;
330bf215546Sopenharmony_ci      }
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci      /* Setup depth stencil view */
333bf215546Sopenharmony_ci      struct pipe_surface *dsv =
334bf215546Sopenharmony_ci         svga_validate_surface_view(svga, svga_surface_dst);
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci      if (!dsv) {
337bf215546Sopenharmony_ci         pipe_surface_reference(&surface, NULL);
338bf215546Sopenharmony_ci         return;
339bf215546Sopenharmony_ci      }
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci      if (box->x == 0 && box->y == 0 && box->width == surface->width &&
342bf215546Sopenharmony_ci          box->height == surface->height) {
343bf215546Sopenharmony_ci         /* clearing whole surface, use direct VGPU10 command */
344bf215546Sopenharmony_ci         assert(svga_surface(dsv)->view_id != SVGA3D_INVALID_ID);
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci         SVGA_RETRY(svga, SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv,
347bf215546Sopenharmony_ci                                                              clear_flags,
348bf215546Sopenharmony_ci                                                              stencil, depth));
349bf215546Sopenharmony_ci      }
350bf215546Sopenharmony_ci      else {
351bf215546Sopenharmony_ci         /* To clear subtexture use software fallback */
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci         util_blitter_save_framebuffer(svga->blitter,
354bf215546Sopenharmony_ci                                       &svga->curr.framebuffer);
355bf215546Sopenharmony_ci         begin_blit(svga);
356bf215546Sopenharmony_ci         util_blitter_clear_depth_stencil(svga->blitter,
357bf215546Sopenharmony_ci                                          dsv, clear_flags,
358bf215546Sopenharmony_ci                                          depth,stencil,
359bf215546Sopenharmony_ci                                          box->x, box->y,
360bf215546Sopenharmony_ci                                          box->width, box->height);
361bf215546Sopenharmony_ci      }
362bf215546Sopenharmony_ci   }
363bf215546Sopenharmony_ci   else {
364bf215546Sopenharmony_ci      /* non depth-stencil formats */
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci      if (data == NULL) {
367bf215546Sopenharmony_ci         /* If data is NULL, the texture image is filled with zeros */
368bf215546Sopenharmony_ci         color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0;
369bf215546Sopenharmony_ci      }
370bf215546Sopenharmony_ci      else {
371bf215546Sopenharmony_ci         util_format_unpack_rgba(surface->format, &color, data, 1);
372bf215546Sopenharmony_ci      }
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci      /* Setup render target view */
375bf215546Sopenharmony_ci      struct pipe_surface *rtv =
376bf215546Sopenharmony_ci         svga_validate_surface_view(svga, svga_surface_dst);
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci      if (!rtv) {
379bf215546Sopenharmony_ci         pipe_surface_reference(&surface, NULL);
380bf215546Sopenharmony_ci         return;
381bf215546Sopenharmony_ci      }
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci      if (box->x == 0 && box->y == 0 && box->width == surface->width &&
384bf215546Sopenharmony_ci          box->height == surface->height) {
385bf215546Sopenharmony_ci         struct pipe_framebuffer_state *curr =  &svga->curr.framebuffer;
386bf215546Sopenharmony_ci         bool int_target = is_integer_target(curr, PIPE_CLEAR_COLOR);
387bf215546Sopenharmony_ci
388bf215546Sopenharmony_ci         if (int_target && !ints_fit_in_floats(&color)) {
389bf215546Sopenharmony_ci            /* To clear full texture with integer format */
390bf215546Sopenharmony_ci            clear_buffers_with_quad(svga, PIPE_CLEAR_COLOR, &color, 0.0, 0);
391bf215546Sopenharmony_ci         }
392bf215546Sopenharmony_ci         else {
393bf215546Sopenharmony_ci            float rgba[4];
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci            if (int_target) {
396bf215546Sopenharmony_ci               rgba[0] = (float) color.i[0];
397bf215546Sopenharmony_ci               rgba[1] = (float) color.i[1];
398bf215546Sopenharmony_ci               rgba[2] = (float) color.i[2];
399bf215546Sopenharmony_ci               rgba[3] = (float) color.i[3];
400bf215546Sopenharmony_ci            }
401bf215546Sopenharmony_ci            else {
402bf215546Sopenharmony_ci               rgba[0] = color.f[0];
403bf215546Sopenharmony_ci               rgba[1] = color.f[1];
404bf215546Sopenharmony_ci               rgba[2] = color.f[2];
405bf215546Sopenharmony_ci               rgba[3] = color.f[3];
406bf215546Sopenharmony_ci            }
407bf215546Sopenharmony_ci
408bf215546Sopenharmony_ci            /* clearing whole surface using VGPU10 command */
409bf215546Sopenharmony_ci            assert(svga_surface(rtv)->view_id != SVGA3D_INVALID_ID);
410bf215546Sopenharmony_ci            SVGA_RETRY(svga, SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv,
411bf215546Sopenharmony_ci                                                                 rgba));
412bf215546Sopenharmony_ci         }
413bf215546Sopenharmony_ci      }
414bf215546Sopenharmony_ci      else {
415bf215546Sopenharmony_ci         /* To clear subtexture use software fallback */
416bf215546Sopenharmony_ci
417bf215546Sopenharmony_ci         /**
418bf215546Sopenharmony_ci          * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D
419bf215546Sopenharmony_ci          * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use
420bf215546Sopenharmony_ci          * util_clear_render_target() for PIPE_TEXTURE_3D.
421bf215546Sopenharmony_ci          */
422bf215546Sopenharmony_ci         if (rtv->texture->target != PIPE_TEXTURE_3D &&
423bf215546Sopenharmony_ci             pipe->screen->is_format_supported(pipe->screen, rtv->format,
424bf215546Sopenharmony_ci                                               rtv->texture->target,
425bf215546Sopenharmony_ci                                               rtv->texture->nr_samples,
426bf215546Sopenharmony_ci                                               rtv->texture->nr_storage_samples,
427bf215546Sopenharmony_ci                                               PIPE_BIND_RENDER_TARGET)) {
428bf215546Sopenharmony_ci            /* clear with quad drawing */
429bf215546Sopenharmony_ci            util_blitter_save_framebuffer(svga->blitter,
430bf215546Sopenharmony_ci                                          &svga->curr.framebuffer);
431bf215546Sopenharmony_ci            begin_blit(svga);
432bf215546Sopenharmony_ci            util_blitter_clear_render_target(svga->blitter,
433bf215546Sopenharmony_ci                                             rtv,
434bf215546Sopenharmony_ci                                             &color,
435bf215546Sopenharmony_ci                                             box->x, box->y,
436bf215546Sopenharmony_ci                                             box->width, box->height);
437bf215546Sopenharmony_ci         }
438bf215546Sopenharmony_ci         else {
439bf215546Sopenharmony_ci            /* clear with map/write/unmap */
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci            /* store layer values */
442bf215546Sopenharmony_ci            unsigned first_layer = rtv->u.tex.first_layer;
443bf215546Sopenharmony_ci            unsigned last_layer = rtv->u.tex.last_layer;
444bf215546Sopenharmony_ci            unsigned box_depth = last_layer - first_layer + 1;
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci            for (unsigned i = 0; i < box_depth; i++) {
447bf215546Sopenharmony_ci               rtv->u.tex.first_layer = rtv->u.tex.last_layer =
448bf215546Sopenharmony_ci                  first_layer + i;
449bf215546Sopenharmony_ci               util_clear_render_target(pipe, rtv, &color, box->x, box->y,
450bf215546Sopenharmony_ci                                        box->width, box->height);
451bf215546Sopenharmony_ci            }
452bf215546Sopenharmony_ci            /* restore layer values */
453bf215546Sopenharmony_ci            rtv->u.tex.first_layer = first_layer;
454bf215546Sopenharmony_ci            rtv->u.tex.last_layer = last_layer;
455bf215546Sopenharmony_ci         }
456bf215546Sopenharmony_ci      }
457bf215546Sopenharmony_ci   }
458bf215546Sopenharmony_ci   pipe_surface_reference(&surface, NULL);
459bf215546Sopenharmony_ci}
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci/**
462bf215546Sopenharmony_ci * \brief  Clear the whole render target using vgpu10 functionality
463bf215546Sopenharmony_ci *
464bf215546Sopenharmony_ci * \param svga[in]  The svga context
465bf215546Sopenharmony_ci * \param dst[in]  The surface to clear
466bf215546Sopenharmony_ci * \param color[in]  Clear color
467bf215546Sopenharmony_ci * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of
468bf215546Sopenharmony_ci * command submission resources.
469bf215546Sopenharmony_ci */
470bf215546Sopenharmony_cistatic enum pipe_error
471bf215546Sopenharmony_cisvga_try_clear_render_target(struct svga_context *svga,
472bf215546Sopenharmony_ci                             struct pipe_surface *dst,
473bf215546Sopenharmony_ci                             const union pipe_color_union *color)
474bf215546Sopenharmony_ci{
475bf215546Sopenharmony_ci   struct pipe_surface *rtv =
476bf215546Sopenharmony_ci      svga_validate_surface_view(svga, svga_surface(dst));
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci   if (!rtv)
479bf215546Sopenharmony_ci      return PIPE_ERROR_OUT_OF_MEMORY;
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_ci   assert(svga_surface(rtv)->view_id != SVGA3D_INVALID_ID);
482bf215546Sopenharmony_ci   return SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, color->f);
483bf215546Sopenharmony_ci }
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci/**
486bf215546Sopenharmony_ci * \brief  Clear part of render target using gallium blitter utilities
487bf215546Sopenharmony_ci *
488bf215546Sopenharmony_ci * \param svga[in]  The svga context
489bf215546Sopenharmony_ci * \param dst[in]  The surface to clear
490bf215546Sopenharmony_ci * \param color[in]  Clear color
491bf215546Sopenharmony_ci * \param dstx[in]  Clear region left
492bf215546Sopenharmony_ci * \param dsty[in]  Clear region top
493bf215546Sopenharmony_ci * \param width[in]  Clear region width
494bf215546Sopenharmony_ci * \param height[in]  Clear region height
495bf215546Sopenharmony_ci */
496bf215546Sopenharmony_cistatic void
497bf215546Sopenharmony_cisvga_blitter_clear_render_target(struct svga_context *svga,
498bf215546Sopenharmony_ci                                 struct pipe_surface *dst,
499bf215546Sopenharmony_ci                                 const union pipe_color_union *color,
500bf215546Sopenharmony_ci                                 unsigned dstx, unsigned dsty,
501bf215546Sopenharmony_ci                                 unsigned width, unsigned height)
502bf215546Sopenharmony_ci{
503bf215546Sopenharmony_ci   begin_blit(svga);
504bf215546Sopenharmony_ci   util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer);
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci   util_blitter_clear_render_target(svga->blitter, dst, color,
507bf215546Sopenharmony_ci                                    dstx, dsty, width, height);
508bf215546Sopenharmony_ci}
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci
511bf215546Sopenharmony_ci/**
512bf215546Sopenharmony_ci * \brief Clear render target pipe callback
513bf215546Sopenharmony_ci *
514bf215546Sopenharmony_ci * \param pipe[in]  The pipe context
515bf215546Sopenharmony_ci * \param dst[in]  The surface to clear
516bf215546Sopenharmony_ci * \param color[in]  Clear color
517bf215546Sopenharmony_ci * \param dstx[in]  Clear region left
518bf215546Sopenharmony_ci * \param dsty[in]  Clear region top
519bf215546Sopenharmony_ci * \param width[in]  Clear region width
520bf215546Sopenharmony_ci * \param height[in]  Clear region height
521bf215546Sopenharmony_ci * \param render_condition_enabled[in]  Whether to use conditional rendering
522bf215546Sopenharmony_ci * to clear (if elsewhere enabled).
523bf215546Sopenharmony_ci */
524bf215546Sopenharmony_cistatic void
525bf215546Sopenharmony_cisvga_clear_render_target(struct pipe_context *pipe,
526bf215546Sopenharmony_ci                         struct pipe_surface *dst,
527bf215546Sopenharmony_ci                         const union pipe_color_union *color,
528bf215546Sopenharmony_ci                         unsigned dstx, unsigned dsty,
529bf215546Sopenharmony_ci                         unsigned width, unsigned height,
530bf215546Sopenharmony_ci                         bool render_condition_enabled)
531bf215546Sopenharmony_ci{
532bf215546Sopenharmony_ci    struct svga_context *svga = svga_context( pipe );
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci    svga_toggle_render_condition(svga, render_condition_enabled, FALSE);
535bf215546Sopenharmony_ci    if (!svga_have_vgpu10(svga) || dstx != 0 || dsty != 0 ||
536bf215546Sopenharmony_ci        width != dst->width || height != dst->height) {
537bf215546Sopenharmony_ci       svga_blitter_clear_render_target(svga, dst, color, dstx, dsty, width,
538bf215546Sopenharmony_ci                                        height);
539bf215546Sopenharmony_ci    } else {
540bf215546Sopenharmony_ci       enum pipe_error ret;
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci       SVGA_RETRY_OOM(svga, ret, svga_try_clear_render_target(svga, dst,
543bf215546Sopenharmony_ci                                                              color));
544bf215546Sopenharmony_ci       assert (ret == PIPE_OK);
545bf215546Sopenharmony_ci    }
546bf215546Sopenharmony_ci    svga_toggle_render_condition(svga, render_condition_enabled, TRUE);
547bf215546Sopenharmony_ci}
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_civoid svga_init_clear_functions(struct svga_context *svga)
550bf215546Sopenharmony_ci{
551bf215546Sopenharmony_ci   svga->pipe.clear_render_target = svga_clear_render_target;
552bf215546Sopenharmony_ci   svga->pipe.clear_texture = svga_clear_texture;
553bf215546Sopenharmony_ci   svga->pipe.clear = svga_clear;
554bf215546Sopenharmony_ci}
555