1/**************************************************************************
2 *
3 * Copyright 2012-2021 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28/*
29 * Shader.cpp --
30 *    Functions that manipulate shader resources.
31 */
32
33
34#include "Shader.h"
35#include "ShaderParse.h"
36#include "State.h"
37#include "Query.h"
38
39#include "Debug.h"
40#include "Format.h"
41
42#include "tgsi/tgsi_ureg.h"
43#include "util/u_gen_mipmap.h"
44#include "util/u_sampler.h"
45#include "util/format/u_format.h"
46
47
48/*
49 * ----------------------------------------------------------------------
50 *
51 * CreateEmptyShader --
52 *
53 *    Update the driver's currently bound constant buffers.
54 *
55 * ----------------------------------------------------------------------
56 */
57
58void *
59CreateEmptyShader(Device *pDevice,
60                  enum pipe_shader_type processor)
61{
62   struct pipe_context *pipe = pDevice->pipe;
63   struct ureg_program *ureg;
64   const struct tgsi_token *tokens;
65   uint nr_tokens;
66
67   if (processor == PIPE_SHADER_GEOMETRY) {
68      return NULL;
69   }
70
71   ureg = ureg_create(processor);
72   if (!ureg)
73      return NULL;
74
75   ureg_END(ureg);
76
77   tokens = ureg_get_tokens(ureg, &nr_tokens);
78   if (!tokens)
79      return NULL;
80
81   ureg_destroy(ureg);
82
83   struct pipe_shader_state state;
84   memset(&state, 0, sizeof state);
85   state.tokens = tokens;
86
87   void *handle;
88   switch (processor) {
89   case PIPE_SHADER_FRAGMENT:
90      handle = pipe->create_fs_state(pipe, &state);
91      break;
92   case PIPE_SHADER_VERTEX:
93      handle = pipe->create_vs_state(pipe, &state);
94      break;
95   case PIPE_SHADER_GEOMETRY:
96      handle = pipe->create_gs_state(pipe, &state);
97      break;
98   default:
99      handle = NULL;
100      assert(0);
101   }
102   assert(handle);
103
104   ureg_free_tokens(tokens);
105
106   return handle;
107}
108
109
110/*
111 * ----------------------------------------------------------------------
112 *
113 * CreateEmptyShader --
114 *
115 *    Update the driver's currently bound constant buffers.
116 *
117 * ----------------------------------------------------------------------
118 */
119
120void
121DeleteEmptyShader(Device *pDevice,
122                  enum pipe_shader_type processor, void *handle)
123{
124   struct pipe_context *pipe = pDevice->pipe;
125
126   if (processor == PIPE_SHADER_GEOMETRY) {
127      assert(handle == NULL);
128      return;
129   }
130
131   assert(handle != NULL);
132   switch (processor) {
133   case PIPE_SHADER_FRAGMENT:
134      pipe->delete_fs_state(pipe, handle);
135      break;
136   case PIPE_SHADER_VERTEX:
137      pipe->delete_vs_state(pipe, handle);
138      break;
139   case PIPE_SHADER_GEOMETRY:
140      pipe->delete_gs_state(pipe, handle);
141      break;
142   default:
143      assert(0);
144   }
145}
146
147
148/*
149 * ----------------------------------------------------------------------
150 *
151 * SetConstantBuffers --
152 *
153 *    Update the driver's currently bound constant buffers.
154 *
155 * ----------------------------------------------------------------------
156 */
157
158static void
159SetConstantBuffers(enum pipe_shader_type shader_type,    // IN
160                   D3D10DDI_HDEVICE hDevice,             // IN
161                   UINT StartBuffer,                     // IN
162                   UINT NumBuffers,                      // IN
163                   const D3D10DDI_HRESOURCE *phBuffers) // IN
164{
165   Device *pDevice = CastDevice(hDevice);
166   struct pipe_context *pipe = pDevice->pipe;
167
168   for (UINT i = 0; i < NumBuffers; i++) {
169      struct pipe_constant_buffer cb;
170      memset(&cb, 0, sizeof cb);
171      cb.buffer = CastPipeResource(phBuffers[i]);
172      cb.buffer_offset = 0;
173      cb.buffer_size = cb.buffer ? cb.buffer->width0 : 0;
174      pipe->set_constant_buffer(pipe,
175                                shader_type,
176                                StartBuffer + i,
177                                FALSE,
178                                &cb);
179   }
180}
181
182
183/*
184 * ----------------------------------------------------------------------
185 *
186 * SetSamplers --
187 *
188 *    Update the driver's currently bound sampler state.
189 *
190 * ----------------------------------------------------------------------
191 */
192
193static void
194SetSamplers(enum pipe_shader_type shader_type,     // IN
195            D3D10DDI_HDEVICE hDevice,              // IN
196            UINT Offset,                          // IN
197            UINT NumSamplers,                       // IN
198            const D3D10DDI_HSAMPLER *phSamplers)  // IN
199{
200   Device *pDevice = CastDevice(hDevice);
201   struct pipe_context *pipe = pDevice->pipe;
202
203   void **samplers = pDevice->samplers[shader_type];
204   for (UINT i = 0; i < NumSamplers; i++) {
205      assert(Offset + i < PIPE_MAX_SAMPLERS);
206      samplers[Offset + i] = CastPipeSamplerState(phSamplers[i]);
207   }
208
209   pipe->bind_sampler_states(pipe, shader_type, 0, PIPE_MAX_SAMPLERS, samplers);
210}
211
212
213/*
214 * ----------------------------------------------------------------------
215 *
216 * SetSamplers --
217 *
218 *    Update the driver's currently bound sampler state.
219 *
220 * ----------------------------------------------------------------------
221 */
222
223static void
224SetShaderResources(enum pipe_shader_type shader_type,                  // IN
225                   D3D10DDI_HDEVICE hDevice,                                   // IN
226                   UINT Offset,                                                // IN
227                   UINT NumViews,                                              // IN
228                   const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews)  // IN
229{
230   Device *pDevice = CastDevice(hDevice);
231   struct pipe_context *pipe = pDevice->pipe;
232
233   assert(Offset + NumViews <= D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
234
235   struct pipe_sampler_view **sampler_views = pDevice->sampler_views[shader_type];
236   for (UINT i = 0; i < NumViews; i++) {
237      struct pipe_sampler_view *sampler_view =
238            CastPipeShaderResourceView(phShaderResourceViews[i]);
239      if (Offset + i < PIPE_MAX_SHADER_SAMPLER_VIEWS) {
240         sampler_views[Offset + i] = sampler_view;
241      } else {
242         if (sampler_view) {
243            LOG_UNSUPPORTED(TRUE);
244            break;
245         }
246      }
247   }
248
249   /*
250    * XXX: Now that the semantics are actually the same in gallium, should
251    * probably think about not updating all always... It should just work.
252    */
253   pipe->set_sampler_views(pipe, shader_type, 0, PIPE_MAX_SHADER_SAMPLER_VIEWS,
254                           0, false, sampler_views);
255}
256
257
258/*
259 * ----------------------------------------------------------------------
260 *
261 * CalcPrivateShaderSize --
262 *
263 *    The CalcPrivateShaderSize function determines the size of
264 *    the user-mode display driver's private region of memory
265 *    (that is, the size of internal driver structures, not the
266 *    size of the resource video memory) for a shader.
267 *
268 * ----------------------------------------------------------------------
269 */
270
271SIZE_T APIENTRY
272CalcPrivateShaderSize(D3D10DDI_HDEVICE hDevice,                                  // IN
273                      __in_ecount (pShaderCode[1]) const UINT *pShaderCode,      // IN
274                      __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures)   // IN
275{
276   return sizeof(Shader);
277}
278
279
280/*
281 * ----------------------------------------------------------------------
282 *
283 * DestroyShader --
284 *
285 *    The DestroyShader function destroys the specified shader object.
286 *    The shader object can be destoyed only if it is not currently
287 *    bound to a display device.
288 *
289 * ----------------------------------------------------------------------
290 */
291
292void APIENTRY
293DestroyShader(D3D10DDI_HDEVICE hDevice,   // IN
294              D3D10DDI_HSHADER hShader)   // IN
295{
296   LOG_ENTRYPOINT();
297
298   struct pipe_context *pipe = CastPipeContext(hDevice);
299   Shader *pShader = CastShader(hShader);
300
301   if (pShader->handle) {
302      switch (pShader->type) {
303      case PIPE_SHADER_FRAGMENT:
304         pipe->delete_fs_state(pipe, pShader->handle);
305         break;
306      case PIPE_SHADER_VERTEX:
307         pipe->delete_vs_state(pipe, pShader->handle);
308         break;
309      case PIPE_SHADER_GEOMETRY:
310         pipe->delete_gs_state(pipe, pShader->handle);
311         break;
312      default:
313         assert(0);
314      }
315   }
316
317   if (pShader->state.tokens) {
318      ureg_free_tokens(pShader->state.tokens);
319   }
320}
321
322
323/*
324 * ----------------------------------------------------------------------
325 *
326 * CalcPrivateSamplerSize --
327 *
328 *    The CalcPrivateSamplerSize function determines the size of the
329 *    user-mode display driver's private region of memory (that is,
330 *    the size of internal driver structures, not the size of the
331 *    resource video memory) for a sampler.
332 *
333 * ----------------------------------------------------------------------
334 */
335
336SIZE_T APIENTRY
337CalcPrivateSamplerSize(D3D10DDI_HDEVICE hDevice,                        // IN
338                       __in const D3D10_DDI_SAMPLER_DESC *pSamplerDesc) // IN
339{
340   return sizeof(SamplerState);
341}
342
343
344static uint
345translate_address_mode(D3D10_DDI_TEXTURE_ADDRESS_MODE AddressMode)
346{
347   switch (AddressMode) {
348   case D3D10_DDI_TEXTURE_ADDRESS_WRAP:
349      return PIPE_TEX_WRAP_REPEAT;
350   case D3D10_DDI_TEXTURE_ADDRESS_MIRROR:
351      return PIPE_TEX_WRAP_MIRROR_REPEAT;
352   case D3D10_DDI_TEXTURE_ADDRESS_CLAMP:
353      return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
354   case D3D10_DDI_TEXTURE_ADDRESS_BORDER:
355      return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
356   case D3D10_DDI_TEXTURE_ADDRESS_MIRRORONCE:
357      return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
358   default:
359      assert(0);
360      return PIPE_TEX_WRAP_REPEAT;
361   }
362}
363
364static uint
365translate_comparison(D3D10_DDI_COMPARISON_FUNC Func)
366{
367   switch (Func) {
368   case D3D10_DDI_COMPARISON_NEVER:
369      return PIPE_FUNC_NEVER;
370   case D3D10_DDI_COMPARISON_LESS:
371      return PIPE_FUNC_LESS;
372   case D3D10_DDI_COMPARISON_EQUAL:
373      return PIPE_FUNC_EQUAL;
374   case D3D10_DDI_COMPARISON_LESS_EQUAL:
375      return PIPE_FUNC_LEQUAL;
376   case D3D10_DDI_COMPARISON_GREATER:
377      return PIPE_FUNC_GREATER;
378   case D3D10_DDI_COMPARISON_NOT_EQUAL:
379      return PIPE_FUNC_NOTEQUAL;
380   case D3D10_DDI_COMPARISON_GREATER_EQUAL:
381      return PIPE_FUNC_GEQUAL;
382   case D3D10_DDI_COMPARISON_ALWAYS:
383      return PIPE_FUNC_ALWAYS;
384   default:
385      assert(0);
386      return PIPE_FUNC_ALWAYS;
387   }
388}
389
390static uint
391translate_filter(D3D10_DDI_FILTER_TYPE Filter)
392{
393   switch (Filter) {
394   case D3D10_DDI_FILTER_TYPE_POINT:
395      return PIPE_TEX_FILTER_NEAREST;
396   case D3D10_DDI_FILTER_TYPE_LINEAR:
397      return PIPE_TEX_FILTER_LINEAR;
398   default:
399      assert(0);
400      return PIPE_TEX_FILTER_NEAREST;
401   }
402}
403
404static uint
405translate_min_filter(D3D10_DDI_FILTER Filter)
406{
407   return translate_filter(D3D10_DDI_DECODE_MIN_FILTER(Filter));
408}
409
410static uint
411translate_mag_filter(D3D10_DDI_FILTER Filter)
412{
413   return translate_filter(D3D10_DDI_DECODE_MAG_FILTER(Filter));
414}
415
416/* Gallium uses a different enum for mipfilters, to accomodate the GL
417 * MIPFILTER_NONE mode.
418 */
419static uint
420translate_mip_filter(D3D10_DDI_FILTER Filter)
421{
422   switch (D3D10_DDI_DECODE_MIP_FILTER(Filter)) {
423   case D3D10_DDI_FILTER_TYPE_POINT:
424      return PIPE_TEX_MIPFILTER_NEAREST;
425   case D3D10_DDI_FILTER_TYPE_LINEAR:
426      return PIPE_TEX_MIPFILTER_LINEAR;
427   default:
428      assert(0);
429      return PIPE_TEX_MIPFILTER_NEAREST;
430   }
431}
432
433/*
434 * ----------------------------------------------------------------------
435 *
436 * CreateSampler --
437 *
438 *    The CreateSampler function creates a sampler.
439 *
440 * ----------------------------------------------------------------------
441 */
442
443void APIENTRY
444CreateSampler(D3D10DDI_HDEVICE hDevice,                        // IN
445              __in const D3D10_DDI_SAMPLER_DESC *pSamplerDesc, // IN
446              D3D10DDI_HSAMPLER hSampler,                      // IN
447              D3D10DDI_HRTSAMPLER hRTSampler)                  // IN
448{
449   LOG_ENTRYPOINT();
450
451   struct pipe_context *pipe = CastPipeContext(hDevice);
452   SamplerState *pSamplerState = CastSamplerState(hSampler);
453
454   struct pipe_sampler_state state;
455
456   memset(&state, 0, sizeof state);
457
458   /* d3d10 has seamless cube filtering always enabled */
459   state.seamless_cube_map = 1;
460
461   /* Wrapping modes. */
462   state.wrap_s = translate_address_mode(pSamplerDesc->AddressU);
463   state.wrap_t = translate_address_mode(pSamplerDesc->AddressV);
464   state.wrap_r = translate_address_mode(pSamplerDesc->AddressW);
465
466   /* Filtering */
467   state.min_img_filter = translate_min_filter(pSamplerDesc->Filter);
468   state.mag_img_filter = translate_mag_filter(pSamplerDesc->Filter);
469   state.min_mip_filter = translate_mip_filter(pSamplerDesc->Filter);
470
471   if (D3D10_DDI_DECODE_IS_ANISOTROPIC_FILTER(pSamplerDesc->Filter)) {
472      state.max_anisotropy = pSamplerDesc->MaxAnisotropy;
473   }
474
475   /* XXX: Handle the following bit.
476    */
477   LOG_UNSUPPORTED(D3D10_DDI_DECODE_IS_TEXT_1BIT_FILTER(pSamplerDesc->Filter));
478
479   /* Comparison. */
480   if (D3D10_DDI_DECODE_IS_COMPARISON_FILTER(pSamplerDesc->Filter)) {
481      state.compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
482      state.compare_func = translate_comparison(pSamplerDesc->ComparisonFunc);
483   }
484
485   state.normalized_coords = 1;
486
487   /* Level of detail. */
488   state.lod_bias = pSamplerDesc->MipLODBias;
489   state.min_lod = pSamplerDesc->MinLOD;
490   state.max_lod = pSamplerDesc->MaxLOD;
491
492   /* Border color. */
493   state.border_color.f[0] = pSamplerDesc->BorderColor[0];
494   state.border_color.f[1] = pSamplerDesc->BorderColor[1];
495   state.border_color.f[2] = pSamplerDesc->BorderColor[2];
496   state.border_color.f[3] = pSamplerDesc->BorderColor[3];
497
498   pSamplerState->handle = pipe->create_sampler_state(pipe, &state);
499}
500
501
502/*
503 * ----------------------------------------------------------------------
504 *
505 * DestroySampler --
506 *
507 *    The DestroySampler function destroys the specified sampler object.
508 *    The sampler object can be destoyed only if it is not currently
509 *    bound to a display device.
510 *
511 * ----------------------------------------------------------------------
512 */
513
514void APIENTRY
515DestroySampler(D3D10DDI_HDEVICE hDevice,     // IN
516               D3D10DDI_HSAMPLER hSampler)   // IN
517{
518   LOG_ENTRYPOINT();
519
520   struct pipe_context *pipe = CastPipeContext(hDevice);
521   SamplerState *pSamplerState = CastSamplerState(hSampler);
522
523   pipe->delete_sampler_state(pipe, pSamplerState->handle);
524}
525
526
527/*
528 * ----------------------------------------------------------------------
529 *
530 * CreateVertexShader --
531 *
532 *    The CreateVertexShader function creates a vertex shader.
533 *
534 * ----------------------------------------------------------------------
535 */
536
537void APIENTRY
538CreateVertexShader(D3D10DDI_HDEVICE hDevice,                                  // IN
539                   __in_ecount (pShaderCode[1]) const UINT *pCode,            // IN
540                   D3D10DDI_HSHADER hShader,                                  // IN
541                   D3D10DDI_HRTSHADER hRTShader,                              // IN
542                   __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures)   // IN
543{
544   LOG_ENTRYPOINT();
545
546   struct pipe_context *pipe = CastPipeContext(hDevice);
547   Shader *pShader = CastShader(hShader);
548
549   pShader->type = PIPE_SHADER_VERTEX;
550   pShader->output_resolved = TRUE;
551
552   memset(&pShader->state, 0, sizeof pShader->state);
553   pShader->state.tokens = Shader_tgsi_translate(pCode, pShader->output_mapping);
554
555   pShader->handle = pipe->create_vs_state(pipe, &pShader->state);
556
557}
558
559
560/*
561 * ----------------------------------------------------------------------
562 *
563 * VsSetShader --
564 *
565 *    The VsSetShader function sets the vertex shader code so that all
566 *    of the subsequent drawing operations use that code.
567 *
568 * ----------------------------------------------------------------------
569 */
570
571void APIENTRY
572VsSetShader(D3D10DDI_HDEVICE hDevice,  // IN
573            D3D10DDI_HSHADER hShader)  // IN
574{
575   LOG_ENTRYPOINT();
576
577   Device *pDevice = CastDevice(hDevice);
578   struct pipe_context *pipe = pDevice->pipe;
579   Shader *pShader = CastShader(hShader);
580   void *state = CastPipeShader(hShader);
581
582   pDevice->bound_vs = pShader;
583   if (!state) {
584      state = pDevice->empty_vs;
585   }
586
587   pipe->bind_vs_state(pipe, state);
588}
589
590
591/*
592 * ----------------------------------------------------------------------
593 *
594 * VsSetShaderResources --
595 *
596 *    The VsSetShaderResources function sets resources for a
597 *    vertex shader.
598 *
599 * ----------------------------------------------------------------------
600 */
601
602void APIENTRY
603VsSetShaderResources(D3D10DDI_HDEVICE hDevice,                                   // IN
604                     UINT Offset,                                                // IN
605                     UINT NumViews,                                              // IN
606                     __in_ecount (NumViews)
607                     const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews)  // IN
608{
609   LOG_ENTRYPOINT();
610
611   SetShaderResources(PIPE_SHADER_VERTEX, hDevice, Offset, NumViews, phShaderResourceViews);
612
613}
614
615
616/*
617 * ----------------------------------------------------------------------
618 *
619 * VsSetConstantBuffers --
620 *
621 *    The VsSetConstantBuffers function sets constant buffers
622 *    for a vertex shader.
623 *
624 * ----------------------------------------------------------------------
625 */
626
627void APIENTRY
628VsSetConstantBuffers(D3D10DDI_HDEVICE hDevice,                                      // IN
629                     UINT StartBuffer,                                              // IN
630                     UINT NumBuffers,                                               // IN
631                     __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers)  // IN
632{
633   LOG_ENTRYPOINT();
634
635   SetConstantBuffers(PIPE_SHADER_VERTEX,
636                      hDevice, StartBuffer, NumBuffers, phBuffers);
637}
638
639
640/*
641 * ----------------------------------------------------------------------
642 *
643 * VsSetSamplers --
644 *
645 *    The VsSetSamplers function sets samplers for a vertex shader.
646 *
647 * ----------------------------------------------------------------------
648 */
649
650void APIENTRY
651VsSetSamplers(D3D10DDI_HDEVICE hDevice,                                       // IN
652              UINT Offset,                                                    // IN
653              UINT NumSamplers,                                               // IN
654              __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers)  // IN
655{
656   LOG_ENTRYPOINT();
657
658   SetSamplers(PIPE_SHADER_VERTEX, hDevice, Offset, NumSamplers, phSamplers);
659
660}
661
662
663/*
664 * ----------------------------------------------------------------------
665 *
666 * CreateGeometryShader --
667 *
668 *    The CreateGeometryShader function creates a geometry shader.
669 *
670 * ----------------------------------------------------------------------
671 */
672
673void APIENTRY
674CreateGeometryShader(D3D10DDI_HDEVICE hDevice,                                // IN
675                     __in_ecount (pShaderCode[1]) const UINT *pShaderCode,    // IN
676                     D3D10DDI_HSHADER hShader,                                // IN
677                     D3D10DDI_HRTSHADER hRTShader,                            // IN
678                     __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN
679{
680   LOG_ENTRYPOINT();
681
682   struct pipe_context *pipe = CastPipeContext(hDevice);
683   Shader *pShader = CastShader(hShader);
684
685   pShader->type = PIPE_SHADER_GEOMETRY;
686   pShader->output_resolved = TRUE;
687
688   memset(&pShader->state, 0, sizeof pShader->state);
689   pShader->state.tokens = Shader_tgsi_translate(pShaderCode, pShader->output_mapping);
690
691   pShader->handle = pipe->create_gs_state(pipe, &pShader->state);
692}
693
694
695/*
696 * ----------------------------------------------------------------------
697 *
698 * GsSetShader --
699 *
700 *    The GsSetShader function sets the geometry shader code so that
701 *    all of the subsequent drawing operations use that code.
702 *
703 * ----------------------------------------------------------------------
704 */
705
706void APIENTRY
707GsSetShader(D3D10DDI_HDEVICE hDevice,  // IN
708            D3D10DDI_HSHADER hShader)  // IN
709{
710   LOG_ENTRYPOINT();
711
712   Device *pDevice = CastDevice(hDevice);
713   struct pipe_context *pipe = CastPipeContext(hDevice);
714   void *state = CastPipeShader(hShader);
715   Shader *pShader = CastShader(hShader);
716
717   assert(pipe->bind_gs_state);
718
719   if (pShader && !pShader->state.tokens) {
720      pDevice->bound_empty_gs = pShader;
721   } else {
722      pDevice->bound_empty_gs = NULL;
723      pipe->bind_gs_state(pipe, state);
724   }
725}
726
727
728/*
729 * ----------------------------------------------------------------------
730 *
731 * GsSetShaderResources --
732 *
733 *    The GsSetShaderResources function sets resources for a
734 *    geometry shader.
735 *
736 * ----------------------------------------------------------------------
737 */
738
739void APIENTRY
740GsSetShaderResources(D3D10DDI_HDEVICE hDevice,                                   // IN
741                     UINT Offset,                                                // IN
742                     UINT NumViews,                                              // IN
743                     __in_ecount (NumViews)
744                     const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews)  // IN
745{
746   LOG_ENTRYPOINT();
747
748   SetShaderResources(PIPE_SHADER_GEOMETRY, hDevice, Offset, NumViews, phShaderResourceViews);
749}
750
751
752/*
753 * ----------------------------------------------------------------------
754 *
755 * GsSetConstantBuffers --
756 *
757 *    The GsSetConstantBuffers function sets constant buffers for
758 *    a geometry shader.
759 *
760 * ----------------------------------------------------------------------
761 */
762
763void APIENTRY
764GsSetConstantBuffers(D3D10DDI_HDEVICE hDevice,                                      // IN
765                     UINT StartBuffer,                                              // IN
766                     UINT NumBuffers,                                               // IN
767                     __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers)  // IN
768{
769   LOG_ENTRYPOINT();
770
771   SetConstantBuffers(PIPE_SHADER_GEOMETRY,
772                      hDevice, StartBuffer, NumBuffers, phBuffers);
773}
774
775
776/*
777 * ----------------------------------------------------------------------
778 *
779 * GsSetSamplers --
780 *
781 *    The GsSetSamplers function sets samplers for a geometry shader.
782 *
783 * ----------------------------------------------------------------------
784 */
785
786void APIENTRY
787GsSetSamplers(D3D10DDI_HDEVICE hDevice,                                       // IN
788              UINT Offset,                                                    // IN
789              UINT NumSamplers,                                               // IN
790              __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers)  // IN
791{
792   LOG_ENTRYPOINT();
793
794   SetSamplers(PIPE_SHADER_GEOMETRY, hDevice, Offset, NumSamplers, phSamplers);
795}
796
797
798/*
799 * ----------------------------------------------------------------------
800 *
801 * CalcPrivateGeometryShaderWithStreamOutput --
802 *
803 *    The CalcPrivateGeometryShaderWithStreamOutput function determines
804 *    the size of the user-mode display driver's private region of memory
805 *    (that is, the size of internal driver structures, not the size of
806 *    the resource video memory) for a geometry shader with stream output.
807 *
808 * ----------------------------------------------------------------------
809 */
810
811SIZE_T APIENTRY
812CalcPrivateGeometryShaderWithStreamOutput(
813   D3D10DDI_HDEVICE hDevice,                                                                             // IN
814   __in const D3D10DDIARG_CREATEGEOMETRYSHADERWITHSTREAMOUTPUT *pCreateGeometryShaderWithStreamOutput,   // IN
815   __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures)                                              // IN
816{
817   LOG_ENTRYPOINT();
818   return sizeof(Shader);
819}
820
821
822/*
823 * ----------------------------------------------------------------------
824 *
825 * CreateGeometryShaderWithStreamOutput --
826 *
827 *    The CreateGeometryShaderWithStreamOutput function creates a
828 *    geometry shader with stream output.
829 *
830 * ----------------------------------------------------------------------
831 */
832
833void APIENTRY
834CreateGeometryShaderWithStreamOutput(
835   D3D10DDI_HDEVICE hDevice,                                                                             // IN
836   __in const D3D10DDIARG_CREATEGEOMETRYSHADERWITHSTREAMOUTPUT *pData,   // IN
837   D3D10DDI_HSHADER hShader,                                                                             // IN
838   D3D10DDI_HRTSHADER hRTShader,                                                                         // IN
839   __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures)                                              // IN
840{
841   LOG_ENTRYPOINT();
842
843   struct pipe_context *pipe = CastPipeContext(hDevice);
844   Shader *pShader = CastShader(hShader);
845   int total_components[PIPE_MAX_SO_BUFFERS] = {0};
846   unsigned num_holes = 0;
847   boolean all_slot_zero = TRUE;
848
849   pShader->type = PIPE_SHADER_GEOMETRY;
850
851   memset(&pShader->state, 0, sizeof pShader->state);
852   if (pData->pShaderCode) {
853      pShader->state.tokens = Shader_tgsi_translate(pData->pShaderCode,
854                                                    pShader->output_mapping);
855   }
856   pShader->output_resolved = (pShader->state.tokens != NULL);
857
858   for (unsigned i = 0; i < pData->NumEntries; ++i) {
859      CONST D3D10DDIARG_STREAM_OUTPUT_DECLARATION_ENTRY* pOutputStreamDecl =
860            &pData->pOutputStreamDecl[i];
861      BYTE RegisterMask = pOutputStreamDecl->RegisterMask;
862      unsigned start_component = 0;
863      unsigned num_components = 0;
864      if (RegisterMask) {
865         while ((RegisterMask & 1) == 0) {
866            ++start_component;
867            RegisterMask >>= 1;
868         }
869         while (RegisterMask) {
870            ++num_components;
871            RegisterMask >>= 1;
872         }
873         assert(start_component < 4);
874         assert(1 <= num_components && num_components <= 4);
875         LOG_UNSUPPORTED(((1 << num_components) - 1) << start_component !=
876                         pOutputStreamDecl->RegisterMask);
877      }
878
879      if (pOutputStreamDecl->RegisterIndex == 0xffffffff) {
880         ++num_holes;
881      } else {
882         unsigned idx = i - num_holes;
883         pShader->state.stream_output.output[idx].start_component =
884            start_component;
885         pShader->state.stream_output.output[idx].num_components =
886            num_components;
887         pShader->state.stream_output.output[idx].output_buffer =
888            pOutputStreamDecl->OutputSlot;
889         pShader->state.stream_output.output[idx].register_index =
890            ShaderFindOutputMapping(pShader, pOutputStreamDecl->RegisterIndex);
891         pShader->state.stream_output.output[idx].dst_offset =
892            total_components[pOutputStreamDecl->OutputSlot];
893         if (pOutputStreamDecl->OutputSlot != 0)
894            all_slot_zero = FALSE;
895      }
896      total_components[pOutputStreamDecl->OutputSlot] += num_components;
897   }
898   pShader->state.stream_output.num_outputs = pData->NumEntries - num_holes;
899   for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; ++i) {
900      /* stream_output.stride[i] is in dwords */
901      if (all_slot_zero) {
902         pShader->state.stream_output.stride[i] =
903            pData->StreamOutputStrideInBytes / sizeof(float);
904      } else {
905         pShader->state.stream_output.stride[i] = total_components[i];
906      }
907   }
908
909   pShader->handle = pipe->create_gs_state(pipe, &pShader->state);
910}
911
912
913/*
914 * ----------------------------------------------------------------------
915 *
916 * SoSetTargets --
917 *
918 *    The SoSetTargets function sets stream output target resources.
919 *
920 * ----------------------------------------------------------------------
921 */
922
923void APIENTRY
924SoSetTargets(D3D10DDI_HDEVICE hDevice,                                     // IN
925             UINT SOTargets,                                               // IN
926             UINT ClearTargets,                                            // IN
927             __in_ecount (SOTargets) const D3D10DDI_HRESOURCE *phResource, // IN
928             __in_ecount (SOTargets) const UINT *pOffsets)                 // IN
929{
930   unsigned i;
931
932   LOG_ENTRYPOINT();
933
934   Device *pDevice = CastDevice(hDevice);
935   struct pipe_context *pipe = pDevice->pipe;
936
937   assert(SOTargets + ClearTargets <= PIPE_MAX_SO_BUFFERS);
938
939   for (i = 0; i < SOTargets; ++i) {
940      Resource *resource = CastResource(phResource[i]);
941      struct pipe_resource *buffer = CastPipeResource(phResource[i]);
942      struct pipe_stream_output_target *so_target =
943         resource ? resource->so_target : NULL;
944
945      if (buffer) {
946         unsigned buffer_size = buffer->width0;
947
948         if (!so_target ||
949             so_target->buffer != buffer ||
950             so_target->buffer_size != buffer_size) {
951            if (so_target) {
952               pipe_so_target_reference(&so_target, NULL);
953            }
954            so_target = pipe->create_stream_output_target(pipe, buffer,
955                                                          0,/*buffer offset*/
956                                                          buffer_size);
957            resource->so_target = so_target;
958         }
959      }
960      pDevice->so_targets[i] = so_target;
961   }
962
963   for (i = 0; i < ClearTargets; ++i) {
964      pDevice->so_targets[SOTargets + i] = NULL;
965   }
966
967   if (!pipe->set_stream_output_targets) {
968      LOG_UNSUPPORTED(pipe->set_stream_output_targets);
969      return;
970   }
971
972   pipe->set_stream_output_targets(pipe, SOTargets, pDevice->so_targets,
973                                   pOffsets);
974}
975
976
977/*
978 * ----------------------------------------------------------------------
979 *
980 * CreatePixelShader --
981 *
982 *    The CreatePixelShader function converts pixel shader code into a
983 *    hardware-specific format and associates this code with a
984 *    shader handle.
985 *
986 * ----------------------------------------------------------------------
987 */
988
989void APIENTRY
990CreatePixelShader(D3D10DDI_HDEVICE hDevice,                                // IN
991                  __in_ecount (pShaderCode[1]) const UINT *pShaderCode,    // IN
992                  D3D10DDI_HSHADER hShader,                                // IN
993                  D3D10DDI_HRTSHADER hRTShader,                            // IN
994                  __in const D3D10DDIARG_STAGE_IO_SIGNATURES *pSignatures) // IN
995{
996   LOG_ENTRYPOINT();
997
998   struct pipe_context *pipe = CastPipeContext(hDevice);
999   Shader *pShader = CastShader(hShader);
1000
1001   pShader->type = PIPE_SHADER_FRAGMENT;
1002   pShader->output_resolved = TRUE;
1003
1004   memset(&pShader->state, 0, sizeof pShader->state);
1005   pShader->state.tokens = Shader_tgsi_translate(pShaderCode,
1006                                                 pShader->output_mapping);
1007
1008   pShader->handle = pipe->create_fs_state(pipe, &pShader->state);
1009
1010}
1011
1012
1013/*
1014 * ----------------------------------------------------------------------
1015 *
1016 * PsSetShader --
1017 *
1018 *    The PsSetShader function sets a pixel shader to be used
1019 *    in all drawing operations.
1020 *
1021 * ----------------------------------------------------------------------
1022 */
1023
1024void APIENTRY
1025PsSetShader(D3D10DDI_HDEVICE hDevice,  // IN
1026            D3D10DDI_HSHADER hShader)  // IN
1027{
1028   LOG_ENTRYPOINT();
1029
1030   Device *pDevice = CastDevice(hDevice);
1031   struct pipe_context *pipe = pDevice->pipe;
1032   void *state = CastPipeShader(hShader);
1033
1034   if (!state) {
1035      state = pDevice->empty_fs;
1036   }
1037
1038   pipe->bind_fs_state(pipe, state);
1039}
1040
1041
1042/*
1043 * ----------------------------------------------------------------------
1044 *
1045 * PsSetShaderResources --
1046 *
1047 *    The PsSetShaderResources function sets resources for a pixel shader.
1048 *
1049 * ----------------------------------------------------------------------
1050 */
1051
1052void APIENTRY
1053PsSetShaderResources(D3D10DDI_HDEVICE hDevice,                                   // IN
1054                     UINT Offset,                                                // IN
1055                     UINT NumViews,                                              // IN
1056                     __in_ecount (NumViews)
1057                     const D3D10DDI_HSHADERRESOURCEVIEW *phShaderResourceViews)  // IN
1058{
1059   LOG_ENTRYPOINT();
1060
1061   SetShaderResources(PIPE_SHADER_FRAGMENT, hDevice, Offset, NumViews, phShaderResourceViews);
1062}
1063
1064
1065/*
1066 * ----------------------------------------------------------------------
1067 *
1068 * PsSetConstantBuffers --
1069 *
1070 *    The PsSetConstantBuffers function sets constant buffers for
1071 *    a pixel shader.
1072 *
1073 * ----------------------------------------------------------------------
1074 */
1075
1076void APIENTRY
1077PsSetConstantBuffers(D3D10DDI_HDEVICE hDevice,                                      // IN
1078                     UINT StartBuffer,                                              // IN
1079                     UINT NumBuffers,                                               // IN
1080                     __in_ecount (NumBuffers) const D3D10DDI_HRESOURCE *phBuffers)  // IN
1081{
1082   LOG_ENTRYPOINT();
1083
1084   SetConstantBuffers(PIPE_SHADER_FRAGMENT,
1085                      hDevice, StartBuffer, NumBuffers, phBuffers);
1086}
1087
1088/*
1089 * ----------------------------------------------------------------------
1090 *
1091 * PsSetSamplers --
1092 *
1093 *    The PsSetSamplers function sets samplers for a pixel shader.
1094 *
1095 * ----------------------------------------------------------------------
1096 */
1097
1098void APIENTRY
1099PsSetSamplers(D3D10DDI_HDEVICE hDevice,                                       // IN
1100              UINT Offset,                                                    // IN
1101              UINT NumSamplers,                                               // IN
1102              __in_ecount (NumSamplers) const D3D10DDI_HSAMPLER *phSamplers)  // IN
1103{
1104   LOG_ENTRYPOINT();
1105
1106   SetSamplers(PIPE_SHADER_FRAGMENT, hDevice, Offset, NumSamplers, phSamplers);
1107}
1108
1109
1110/*
1111 * ----------------------------------------------------------------------
1112 *
1113 * ShaderResourceViewReadAfterWriteHazard --
1114 *
1115 *    The ShaderResourceViewReadAfterWriteHazard function informs
1116 *    the usermode display driver that the specified resource was
1117 *    used as an output from the graphics processing unit (GPU)
1118 *    and that the resource will be used as an input to the GPU.
1119 *    A shader resource view is also provided to indicate which
1120 *    view caused the hazard.
1121 *
1122 * ----------------------------------------------------------------------
1123 */
1124
1125void APIENTRY
1126ShaderResourceViewReadAfterWriteHazard(D3D10DDI_HDEVICE hDevice,                          // IN
1127                                       D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView,  // IN
1128                                       D3D10DDI_HRESOURCE hResource)                      // IN
1129{
1130   LOG_ENTRYPOINT();
1131
1132   /* Not actually necessary */
1133}
1134
1135
1136/*
1137 * ----------------------------------------------------------------------
1138 *
1139 * CalcPrivateShaderResourceViewSize --
1140 *
1141 *    The CalcPrivateShaderResourceViewSize function determines the size
1142 *    of the usermode display driver's private region of memory
1143 *    (that is, the size of internal driver structures, not the size of
1144 *    the resource video memory) for a shader resource view.
1145 *
1146 * ----------------------------------------------------------------------
1147 */
1148
1149SIZE_T APIENTRY
1150CalcPrivateShaderResourceViewSize(
1151   D3D10DDI_HDEVICE hDevice,                                                     // IN
1152   __in const D3D10DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView)   // IN
1153{
1154   return sizeof(ShaderResourceView);
1155}
1156
1157
1158/*
1159 * ----------------------------------------------------------------------
1160 *
1161 * CalcPrivateShaderResourceViewSize --
1162 *
1163 *    The CalcPrivateShaderResourceViewSize function determines the size
1164 *    of the usermode display driver's private region of memory
1165 *    (that is, the size of internal driver structures, not the size of
1166 *    the resource video memory) for a shader resource view.
1167 *
1168 * ----------------------------------------------------------------------
1169 */
1170
1171SIZE_T APIENTRY
1172CalcPrivateShaderResourceViewSize1(
1173   D3D10DDI_HDEVICE hDevice,                                                     // IN
1174   __in const D3D10_1DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView)   // IN
1175{
1176   return sizeof(ShaderResourceView);
1177}
1178
1179
1180/*
1181 * ----------------------------------------------------------------------
1182 *
1183 * CreateShaderResourceView --
1184 *
1185 *    The CreateShaderResourceView function creates a shader
1186 *    resource view.
1187 *
1188 * ----------------------------------------------------------------------
1189 */
1190
1191void APIENTRY
1192CreateShaderResourceView(
1193   D3D10DDI_HDEVICE hDevice,                                                     // IN
1194   __in const D3D10DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView,   // IN
1195   D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView,                             // IN
1196   D3D10DDI_HRTSHADERRESOURCEVIEW hRTShaderResourceView)                         // IN
1197{
1198   LOG_ENTRYPOINT();
1199
1200   struct pipe_context *pipe = CastPipeContext(hDevice);
1201   ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView);
1202   struct pipe_resource *resource;
1203   enum pipe_format format;
1204
1205   struct pipe_sampler_view desc;
1206   memset(&desc, 0, sizeof desc);
1207   resource = CastPipeResource(pCreateSRView->hDrvResource);
1208   format = FormatTranslate(pCreateSRView->Format, FALSE);
1209
1210   u_sampler_view_default_template(&desc,
1211                                   resource,
1212                                   format);
1213
1214   switch (pCreateSRView->ResourceDimension) {
1215   case D3D10DDIRESOURCE_BUFFER: {
1216         const struct util_format_description *fdesc = util_format_description(format);
1217         desc.u.buf.offset = pCreateSRView->Buffer.FirstElement *
1218                             (fdesc->block.bits / 8) * fdesc->block.width;
1219         desc.u.buf.size = pCreateSRView->Buffer.NumElements *
1220                             (fdesc->block.bits / 8) * fdesc->block.width;
1221      }
1222      break;
1223   case D3D10DDIRESOURCE_TEXTURE1D:
1224      desc.u.tex.first_level = pCreateSRView->Tex1D.MostDetailedMip;
1225      desc.u.tex.last_level = pCreateSRView->Tex1D.MipLevels - 1 + desc.u.tex.first_level;
1226      desc.u.tex.first_layer = pCreateSRView->Tex1D.FirstArraySlice;
1227      desc.u.tex.last_layer = pCreateSRView->Tex1D.ArraySize - 1 + desc.u.tex.first_layer;
1228      assert(pCreateSRView->Tex1D.MipLevels != 0 && pCreateSRView->Tex1D.MipLevels != (UINT)-1);
1229      assert(pCreateSRView->Tex1D.ArraySize != 0 && pCreateSRView->Tex1D.ArraySize != (UINT)-1);
1230      break;
1231   case D3D10DDIRESOURCE_TEXTURE2D:
1232      desc.u.tex.first_level = pCreateSRView->Tex2D.MostDetailedMip;
1233      desc.u.tex.last_level = pCreateSRView->Tex2D.MipLevels - 1 + desc.u.tex.first_level;
1234      desc.u.tex.first_layer = pCreateSRView->Tex2D.FirstArraySlice;
1235      desc.u.tex.last_layer = pCreateSRView->Tex2D.ArraySize - 1 + desc.u.tex.first_layer;
1236      assert(pCreateSRView->Tex2D.MipLevels != 0 && pCreateSRView->Tex2D.MipLevels != (UINT)-1);
1237      assert(pCreateSRView->Tex2D.ArraySize != 0 && pCreateSRView->Tex2D.ArraySize != (UINT)-1);
1238      break;
1239   case D3D10DDIRESOURCE_TEXTURE3D:
1240      desc.u.tex.first_level = pCreateSRView->Tex3D.MostDetailedMip;
1241      desc.u.tex.last_level = pCreateSRView->Tex3D.MipLevels - 1 + desc.u.tex.first_level;
1242      /* layer info filled in by default_template */
1243      assert(pCreateSRView->Tex3D.MipLevels != 0 && pCreateSRView->Tex3D.MipLevels != (UINT)-1);
1244      break;
1245   case D3D10DDIRESOURCE_TEXTURECUBE:
1246      desc.u.tex.first_level = pCreateSRView->TexCube.MostDetailedMip;
1247      desc.u.tex.last_level = pCreateSRView->TexCube.MipLevels - 1 + desc.u.tex.first_level;
1248      /* layer info filled in by default_template */
1249      assert(pCreateSRView->TexCube.MipLevels != 0 && pCreateSRView->TexCube.MipLevels != (UINT)-1);
1250      break;
1251   default:
1252      assert(0);
1253      return;
1254   }
1255
1256   pSRView->handle = pipe->create_sampler_view(pipe, resource, &desc);
1257}
1258
1259
1260/*
1261 * ----------------------------------------------------------------------
1262 *
1263 * CreateShaderResourceView1 --
1264 *
1265 *    The CreateShaderResourceView function creates a shader
1266 *    resource view.
1267 *
1268 * ----------------------------------------------------------------------
1269 */
1270
1271void APIENTRY
1272CreateShaderResourceView1(
1273   D3D10DDI_HDEVICE hDevice,                                                     // IN
1274   __in const D3D10_1DDIARG_CREATESHADERRESOURCEVIEW *pCreateSRView,   // IN
1275   D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView,                             // IN
1276   D3D10DDI_HRTSHADERRESOURCEVIEW hRTShaderResourceView)                         // IN
1277{
1278   LOG_ENTRYPOINT();
1279
1280   struct pipe_context *pipe = CastPipeContext(hDevice);
1281   ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView);
1282   struct pipe_resource *resource;
1283   enum pipe_format format;
1284
1285   struct pipe_sampler_view desc;
1286   memset(&desc, 0, sizeof desc);
1287   resource = CastPipeResource(pCreateSRView->hDrvResource);
1288   format = FormatTranslate(pCreateSRView->Format, FALSE);
1289
1290   u_sampler_view_default_template(&desc,
1291                                   resource,
1292                                   format);
1293
1294   switch (pCreateSRView->ResourceDimension) {
1295   case D3D10DDIRESOURCE_BUFFER: {
1296         const struct util_format_description *fdesc = util_format_description(format);
1297         desc.u.buf.offset = pCreateSRView->Buffer.FirstElement *
1298                             (fdesc->block.bits / 8) * fdesc->block.width;
1299         desc.u.buf.size = pCreateSRView->Buffer.NumElements *
1300                             (fdesc->block.bits / 8) * fdesc->block.width;
1301      }
1302      break;
1303   case D3D10DDIRESOURCE_TEXTURE1D:
1304      desc.u.tex.first_level = pCreateSRView->Tex1D.MostDetailedMip;
1305      desc.u.tex.last_level = pCreateSRView->Tex1D.MipLevels - 1 + desc.u.tex.first_level;
1306      desc.u.tex.first_layer = pCreateSRView->Tex1D.FirstArraySlice;
1307      desc.u.tex.last_layer = pCreateSRView->Tex1D.ArraySize - 1 + desc.u.tex.first_layer;
1308      assert(pCreateSRView->Tex1D.MipLevels != 0 && pCreateSRView->Tex1D.MipLevels != (UINT)-1);
1309      assert(pCreateSRView->Tex1D.ArraySize != 0 && pCreateSRView->Tex1D.ArraySize != (UINT)-1);
1310      break;
1311   case D3D10DDIRESOURCE_TEXTURE2D:
1312      desc.u.tex.first_level = pCreateSRView->Tex2D.MostDetailedMip;
1313      desc.u.tex.last_level = pCreateSRView->Tex2D.MipLevels - 1 + desc.u.tex.first_level;
1314      desc.u.tex.first_layer = pCreateSRView->Tex2D.FirstArraySlice;
1315      desc.u.tex.last_layer = pCreateSRView->Tex2D.ArraySize - 1 + desc.u.tex.first_layer;
1316      assert(pCreateSRView->Tex2D.MipLevels != 0 && pCreateSRView->Tex2D.MipLevels != (UINT)-1);
1317      assert(pCreateSRView->Tex2D.ArraySize != 0 && pCreateSRView->Tex2D.ArraySize != (UINT)-1);
1318      break;
1319   case D3D10DDIRESOURCE_TEXTURE3D:
1320      desc.u.tex.first_level = pCreateSRView->Tex3D.MostDetailedMip;
1321      desc.u.tex.last_level = pCreateSRView->Tex3D.MipLevels - 1 + desc.u.tex.first_level;
1322      /* layer info filled in by default_template */
1323      assert(pCreateSRView->Tex3D.MipLevels != 0 && pCreateSRView->Tex3D.MipLevels != (UINT)-1);
1324      break;
1325   case D3D10DDIRESOURCE_TEXTURECUBE:
1326      desc.u.tex.first_level = pCreateSRView->TexCube.MostDetailedMip;
1327      desc.u.tex.last_level = pCreateSRView->TexCube.MipLevels - 1 + desc.u.tex.first_level;
1328      desc.u.tex.first_layer = pCreateSRView->TexCube.First2DArrayFace;
1329      desc.u.tex.last_layer = 6*pCreateSRView->TexCube.NumCubes - 1 +
1330                              pCreateSRView->TexCube.First2DArrayFace;
1331      assert(pCreateSRView->TexCube.MipLevels != 0 && pCreateSRView->TexCube.MipLevels != (UINT)-1);
1332      break;
1333   default:
1334      assert(0);
1335      return;
1336   }
1337
1338   pSRView->handle = pipe->create_sampler_view(pipe, resource, &desc);
1339}
1340
1341
1342/*
1343 * ----------------------------------------------------------------------
1344 *
1345 * DestroyShaderResourceView --
1346 *
1347 *    The DestroyShaderResourceView function destroys the specified
1348 *    shader resource view object. The shader resource view object
1349 *    can be destoyed only if it is not currently bound to a
1350 *    display device.
1351 *
1352 * ----------------------------------------------------------------------
1353 */
1354
1355void APIENTRY
1356DestroyShaderResourceView(D3D10DDI_HDEVICE hDevice,                           // IN
1357                          D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView)   // IN
1358{
1359   LOG_ENTRYPOINT();
1360
1361   ShaderResourceView *pSRView = CastShaderResourceView(hShaderResourceView);
1362
1363   pipe_sampler_view_reference(&pSRView->handle, NULL);
1364}
1365
1366
1367/*
1368 * ----------------------------------------------------------------------
1369 *
1370 * GenMips --
1371 *
1372 *    The GenMips function generates the lower MIP-map levels
1373 *    on the specified shader-resource view.
1374 *
1375 * ----------------------------------------------------------------------
1376 */
1377
1378void APIENTRY
1379GenMips(D3D10DDI_HDEVICE hDevice,                           // IN
1380        D3D10DDI_HSHADERRESOURCEVIEW hShaderResourceView)   // IN
1381{
1382   LOG_ENTRYPOINT();
1383
1384   Device *pDevice = CastDevice(hDevice);
1385   if (!CheckPredicate(pDevice)) {
1386      return;
1387   }
1388
1389   struct pipe_context *pipe = pDevice->pipe;
1390   struct pipe_sampler_view *sampler_view = CastPipeShaderResourceView(hShaderResourceView);
1391
1392   util_gen_mipmap(pipe,
1393                   sampler_view->texture,
1394                   sampler_view->format,
1395                   sampler_view->u.tex.first_level,
1396                   sampler_view->u.tex.last_level,
1397                   sampler_view->u.tex.first_layer,
1398                   sampler_view->u.tex.last_layer,
1399                   PIPE_TEX_FILTER_LINEAR);
1400}
1401
1402
1403unsigned
1404ShaderFindOutputMapping(Shader *shader, unsigned registerIndex)
1405{
1406   if (!shader || !shader->state.tokens)
1407      return registerIndex;
1408
1409   for (unsigned i = 0; i < PIPE_MAX_SHADER_OUTPUTS; ++i) {
1410      if (shader->output_mapping[i] == registerIndex)
1411         return i;
1412   }
1413   return registerIndex;
1414}
1415