OSDN Git Service

Do CSC/scaling from 8bit 420 YUV to RGB32 in the common path
[android-x86/hardware-intel-common-vaapi.git] / src / gen9_post_processing.c
1 /*
2  * Copyright © 2014 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sub license, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30
31 #include "intel_batchbuffer.h"
32 #include "intel_driver.h"
33 #include "i965_defines.h"
34 #include "i965_structs.h"
35 #include "i965_drv_video.h"
36 #include "i965_post_processing.h"
37 #include "i965_render.h"
38 #include "intel_media.h"
39
40 #include "i965_yuv_coefs.h"
41 #include "gen8_post_processing.h"
42 #include "gen75_picture_process.h"
43 #include "intel_gen_vppapi.h"
44 #include "intel_common_vpp_internal.h"
45
46 static const uint32_t pp_null_gen9[][4] = {
47 };
48
49 static const uint32_t pp_nv12_load_save_nv12_gen9[][4] = {
50 #include "shaders/post_processing/gen9/pl2_to_pl2.g9b"
51 };
52
53 static const uint32_t pp_nv12_load_save_pl3_gen9[][4] = {
54 #include "shaders/post_processing/gen9/pl2_to_pl3.g9b"
55 };
56
57 static const uint32_t pp_pl3_load_save_nv12_gen9[][4] = {
58 #include "shaders/post_processing/gen9/pl3_to_pl2.g9b"
59 };
60
61 static const uint32_t pp_pl3_load_save_pl3_gen9[][4] = {
62 #include "shaders/post_processing/gen9/pl3_to_pl3.g9b"
63 };
64
65 static const uint32_t pp_nv12_scaling_gen9[][4] = {
66 #include "shaders/post_processing/gen9/pl2_to_pl2.g9b"
67 };
68
69 static const uint32_t pp_nv12_avs_gen9[][4] = {
70 #include "shaders/post_processing/gen9/pl2_to_pl2.g9b"
71 };
72
73 static const uint32_t pp_nv12_dndi_gen9[][4] = {
74 };
75
76 static const uint32_t pp_nv12_dn_gen9[][4] = {
77 };
78
79 static const uint32_t pp_nv12_load_save_pa_gen9[][4] = {
80 #include "shaders/post_processing/gen9/pl2_to_pa.g9b"
81 };
82
83 static const uint32_t pp_pl3_load_save_pa_gen9[][4] = {
84 #include "shaders/post_processing/gen9/pl3_to_pa.g9b"
85 };
86
87 static const uint32_t pp_pa_load_save_nv12_gen9[][4] = {
88 #include "shaders/post_processing/gen9/pa_to_pl2.g9b"
89 };
90
91 static const uint32_t pp_pa_load_save_pl3_gen9[][4] = {
92 #include "shaders/post_processing/gen9/pa_to_pl3.g9b"
93 };
94
95 static const uint32_t pp_pa_load_save_pa_gen9[][4] = {
96 #include "shaders/post_processing/gen9/pa_to_pa.g9b"
97 };
98
99 static const uint32_t pp_rgbx_load_save_nv12_gen9[][4] = {
100 #include "shaders/post_processing/gen9/rgbx_to_nv12.g9b"
101 };
102
103 static const uint32_t pp_nv12_load_save_rgbx_gen9[][4] = {
104 #include "shaders/post_processing/gen9/pl2_to_rgbx.g9b"
105 };
106
107 #define MAX_SCALING_SURFACES    16
108
109 #define DEFAULT_MOCS    0x02
110
111 static const uint32_t pp_10bit_scaling_gen9[][4] = {
112 #include "shaders/post_processing/gen9/conv_p010.g9b"
113 };
114
115 static const uint32_t pp_yuv420p8_scaling_gen9[][4] = {
116 #include "shaders/post_processing/gen9/conv_nv12.g9b"
117 };
118
119 static const uint32_t pp_10bit_8bit_scaling_gen9[][4] = {
120 #include "shaders/post_processing/gen9/conv_10bit_8bit.g9b"
121 };
122
123 static const uint32_t pp_8bit_420_rgb32_scaling_gen9[][4] = {
124 #include "shaders/post_processing/gen9/conv_8bit_420_rgb32.g9b"
125 };
126
127 struct i965_kernel pp_common_scaling_gen9[] = {
128     {
129         "10bit to 10bit",
130         0,
131         pp_10bit_scaling_gen9,
132         sizeof(pp_10bit_scaling_gen9),
133         NULL,
134     },
135
136     {
137         "8bit to 8bit",
138         1,
139         pp_yuv420p8_scaling_gen9,
140         sizeof(pp_yuv420p8_scaling_gen9),
141         NULL,
142     },
143
144     {
145         "10bit to 8bit",
146         2,
147         pp_10bit_8bit_scaling_gen9,
148         sizeof(pp_10bit_8bit_scaling_gen9),
149         NULL,
150     },
151
152     {
153         "8bit 420 to rgb32",
154         3,
155         pp_8bit_420_rgb32_scaling_gen9,
156         sizeof(pp_8bit_420_rgb32_scaling_gen9),
157         NULL,
158     },
159 };
160
161 static struct pp_module pp_modules_gen9[] = {
162     {
163         {
164             "NULL module (for testing)",
165             PP_NULL,
166             pp_null_gen9,
167             sizeof(pp_null_gen9),
168             NULL,
169         },
170
171         pp_null_initialize,
172     },
173
174     {
175         {
176             "NV12_NV12",
177             PP_NV12_LOAD_SAVE_N12,
178             pp_nv12_load_save_nv12_gen9,
179             sizeof(pp_nv12_load_save_nv12_gen9),
180             NULL,
181         },
182
183         gen8_pp_plx_avs_initialize,
184     },
185
186     {
187         {
188             "NV12_PL3",
189             PP_NV12_LOAD_SAVE_PL3,
190             pp_nv12_load_save_pl3_gen9,
191             sizeof(pp_nv12_load_save_pl3_gen9),
192             NULL,
193         },
194         gen8_pp_plx_avs_initialize,
195     },
196
197     {
198         {
199             "PL3_NV12",
200             PP_PL3_LOAD_SAVE_N12,
201             pp_pl3_load_save_nv12_gen9,
202             sizeof(pp_pl3_load_save_nv12_gen9),
203             NULL,
204         },
205
206         gen8_pp_plx_avs_initialize,
207     },
208
209     {
210         {
211             "PL3_PL3",
212             PP_PL3_LOAD_SAVE_PL3,
213             pp_pl3_load_save_pl3_gen9,
214             sizeof(pp_pl3_load_save_pl3_gen9),
215             NULL,
216         },
217
218         gen8_pp_plx_avs_initialize,
219     },
220
221     {
222         {
223             "NV12 Scaling module",
224             PP_NV12_SCALING,
225             pp_nv12_scaling_gen9,
226             sizeof(pp_nv12_scaling_gen9),
227             NULL,
228         },
229
230         gen8_pp_plx_avs_initialize,
231     },
232
233     {
234         {
235             "NV12 AVS module",
236             PP_NV12_AVS,
237             pp_nv12_avs_gen9,
238             sizeof(pp_nv12_avs_gen9),
239             NULL,
240         },
241
242         gen8_pp_plx_avs_initialize,
243     },
244
245     {
246         {
247             "NV12 DNDI module",
248             PP_NV12_DNDI,
249             pp_nv12_dndi_gen9,
250             sizeof(pp_nv12_dndi_gen9),
251             NULL,
252         },
253
254         pp_null_initialize,
255     },
256
257     {
258         {
259             "NV12 DN module",
260             PP_NV12_DN,
261             pp_nv12_dn_gen9,
262             sizeof(pp_nv12_dn_gen9),
263             NULL,
264         },
265
266         pp_null_initialize,
267     },
268     {
269         {
270             "NV12_PA module",
271             PP_NV12_LOAD_SAVE_PA,
272             pp_nv12_load_save_pa_gen9,
273             sizeof(pp_nv12_load_save_pa_gen9),
274             NULL,
275         },
276
277         gen8_pp_plx_avs_initialize,
278     },
279
280     {
281         {
282             "PL3_PA module",
283             PP_PL3_LOAD_SAVE_PA,
284             pp_pl3_load_save_pa_gen9,
285             sizeof(pp_pl3_load_save_pa_gen9),
286             NULL,
287         },
288
289         gen8_pp_plx_avs_initialize,
290     },
291
292     {
293         {
294             "PA_NV12 module",
295             PP_PA_LOAD_SAVE_NV12,
296             pp_pa_load_save_nv12_gen9,
297             sizeof(pp_pa_load_save_nv12_gen9),
298             NULL,
299         },
300
301         gen8_pp_plx_avs_initialize,
302     },
303
304     {
305         {
306             "PA_PL3 module",
307             PP_PA_LOAD_SAVE_PL3,
308             pp_pa_load_save_pl3_gen9,
309             sizeof(pp_pa_load_save_pl3_gen9),
310             NULL,
311         },
312
313         gen8_pp_plx_avs_initialize,
314     },
315
316     {
317         {
318             "PA_PA module",
319             PP_PA_LOAD_SAVE_PA,
320             pp_pa_load_save_pa_gen9,
321             sizeof(pp_pa_load_save_pa_gen9),
322             NULL,
323         },
324
325         gen8_pp_plx_avs_initialize,
326     },
327
328     {
329         {
330             "RGBX_NV12 module",
331             PP_RGBX_LOAD_SAVE_NV12,
332             pp_rgbx_load_save_nv12_gen9,
333             sizeof(pp_rgbx_load_save_nv12_gen9),
334             NULL,
335         },
336
337         gen8_pp_plx_avs_initialize,
338     },
339
340     {
341         {
342             "NV12_RGBX module",
343             PP_NV12_LOAD_SAVE_RGBX,
344             pp_nv12_load_save_rgbx_gen9,
345             sizeof(pp_nv12_load_save_rgbx_gen9),
346             NULL,
347         },
348
349         gen8_pp_plx_avs_initialize,
350     },
351 };
352
353 static const AVSConfig gen9_avs_config = {
354     .coeff_frac_bits = 6,
355     .coeff_epsilon = 1.0f / (1U << 6),
356     .num_phases = 31,
357     .num_luma_coeffs = 8,
358     .num_chroma_coeffs = 4,
359
360     .coeff_range = {
361         .lower_bound = {
362             .y_k_h = { -2, -2, -2, -2, -2, -2, -2, -2 },
363             .y_k_v = { -2, -2, -2, -2, -2, -2, -2, -2 },
364             .uv_k_h = { -2, -2, -2, -2 },
365             .uv_k_v = { -2, -2, -2, -2 },
366         },
367         .upper_bound = {
368             .y_k_h = { 2, 2, 2, 2, 2, 2, 2, 2 },
369             .y_k_v = { 2, 2, 2, 2, 2, 2, 2, 2 },
370             .uv_k_h = { 2, 2, 2, 2 },
371             .uv_k_v = { 2, 2, 2, 2 },
372         },
373     },
374 };
375
376 static void
377 gen9_pp_pipeline_select(VADriverContextP ctx,
378                         struct i965_post_processing_context *pp_context)
379 {
380     struct intel_batchbuffer *batch = pp_context->batch;
381
382     BEGIN_BATCH(batch, 1);
383     OUT_BATCH(batch,
384               CMD_PIPELINE_SELECT |
385               PIPELINE_SELECT_MEDIA |
386               GEN9_FORCE_MEDIA_AWAKE_ON |
387               GEN9_MEDIA_DOP_GATE_OFF |
388               GEN9_PIPELINE_SELECTION_MASK |
389               GEN9_MEDIA_DOP_GATE_MASK |
390               GEN9_FORCE_MEDIA_AWAKE_MASK);
391     ADVANCE_BATCH(batch);
392 }
393
394 static void
395 gen9_pp_state_base_address(VADriverContextP ctx,
396                            struct i965_post_processing_context *pp_context)
397 {
398     struct intel_batchbuffer *batch = pp_context->batch;
399
400     BEGIN_BATCH(batch, 19);
401     OUT_BATCH(batch, CMD_STATE_BASE_ADDRESS | (19 - 2));
402     /* DW1 Generate state address */
403     OUT_BATCH(batch, 0 | BASE_ADDRESS_MODIFY);
404     OUT_BATCH(batch, 0);
405     OUT_BATCH(batch, 0);
406     /* DW4-5 Surface state address */
407     OUT_RELOC64(batch, pp_context->surface_state_binding_table.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, BASE_ADDRESS_MODIFY); /* Surface state base address */
408     /* DW6-7 Dynamic state address */
409     OUT_RELOC64(batch, pp_context->dynamic_state.bo, I915_GEM_DOMAIN_RENDER | I915_GEM_DOMAIN_SAMPLER,
410                 0, 0 | BASE_ADDRESS_MODIFY);
411
412     /* DW8. Indirect object address */
413     OUT_BATCH(batch, 0 | BASE_ADDRESS_MODIFY);
414     OUT_BATCH(batch, 0);
415
416     /* DW10-11 Instruction base address */
417     OUT_RELOC64(batch, pp_context->instruction_state.bo, I915_GEM_DOMAIN_INSTRUCTION, 0, BASE_ADDRESS_MODIFY);
418
419     OUT_BATCH(batch, 0xFFFF0000 | BASE_ADDRESS_MODIFY);
420     OUT_BATCH(batch, 0xFFFF0000 | BASE_ADDRESS_MODIFY);
421     OUT_BATCH(batch, 0xFFFF0000 | BASE_ADDRESS_MODIFY);
422     OUT_BATCH(batch, 0xFFFF0000 | BASE_ADDRESS_MODIFY);
423
424     /* Bindless surface state base address */
425     OUT_BATCH(batch, 0 | BASE_ADDRESS_MODIFY);
426     OUT_BATCH(batch, 0);
427     OUT_BATCH(batch, 0xfffff000);
428
429     ADVANCE_BATCH(batch);
430 }
431
432 static void
433 gen9_pp_end_pipeline(VADriverContextP ctx,
434                      struct i965_post_processing_context *pp_context)
435 {
436     struct intel_batchbuffer *batch = pp_context->batch;
437
438     BEGIN_BATCH(batch, 1);
439     OUT_BATCH(batch,
440               CMD_PIPELINE_SELECT |
441               PIPELINE_SELECT_MEDIA |
442               GEN9_FORCE_MEDIA_AWAKE_OFF |
443               GEN9_MEDIA_DOP_GATE_ON |
444               GEN9_PIPELINE_SELECTION_MASK |
445               GEN9_MEDIA_DOP_GATE_MASK |
446               GEN9_FORCE_MEDIA_AWAKE_MASK);
447     ADVANCE_BATCH(batch);
448 }
449
450 static void
451 gen9_pp_pipeline_setup(VADriverContextP ctx,
452                        struct i965_post_processing_context *pp_context)
453 {
454     struct intel_batchbuffer *batch = pp_context->batch;
455
456     intel_batchbuffer_start_atomic(batch, 0x1000);
457     intel_batchbuffer_emit_mi_flush(batch);
458     gen9_pp_pipeline_select(ctx, pp_context);
459     gen9_pp_state_base_address(ctx, pp_context);
460     gen8_pp_vfe_state(ctx, pp_context);
461     gen8_pp_curbe_load(ctx, pp_context);
462     gen8_interface_descriptor_load(ctx, pp_context);
463     gen8_pp_object_walker(ctx, pp_context);
464     gen9_pp_end_pipeline(ctx, pp_context);
465     intel_batchbuffer_end_atomic(batch);
466 }
467
468 static VAStatus
469 gen9_post_processing(VADriverContextP ctx,
470                      struct i965_post_processing_context *pp_context,
471                      const struct i965_surface *src_surface,
472                      const VARectangle *src_rect,
473                      struct i965_surface *dst_surface,
474                      const VARectangle *dst_rect,
475                      int pp_index,
476                      void * filter_param)
477 {
478     VAStatus va_status;
479
480     va_status = gen8_pp_initialize(ctx, pp_context,
481                                    src_surface,
482                                    src_rect,
483                                    dst_surface,
484                                    dst_rect,
485                                    pp_index,
486                                    filter_param);
487
488     if (va_status == VA_STATUS_SUCCESS) {
489         gen8_pp_states_setup(ctx, pp_context);
490         gen9_pp_pipeline_setup(ctx, pp_context);
491     }
492
493     return va_status;
494 }
495
496 static void
497 gen9_vpp_scaling_sample_state(VADriverContextP ctx,
498                               struct i965_gpe_context *gpe_context,
499                               VARectangle *src_rect,
500                               VARectangle *dst_rect)
501 {
502     struct gen8_sampler_state *sampler_state;
503
504     if (gpe_context == NULL || !src_rect || !dst_rect)
505         return;
506     dri_bo_map(gpe_context->sampler.bo, 1);
507
508     if (gpe_context->sampler.bo->virtual == NULL)
509         return;
510
511     assert(gpe_context->sampler.bo->virtual);
512
513     sampler_state = (struct gen8_sampler_state *)
514                     (gpe_context->sampler.bo->virtual + gpe_context->sampler.offset);
515
516     memset(sampler_state, 0, sizeof(*sampler_state));
517
518     if ((src_rect->width == dst_rect->width) &&
519         (src_rect->height == dst_rect->height)) {
520         sampler_state->ss0.min_filter = I965_MAPFILTER_NEAREST;
521         sampler_state->ss0.mag_filter = I965_MAPFILTER_NEAREST;
522     } else {
523         sampler_state->ss0.min_filter = I965_MAPFILTER_LINEAR;
524         sampler_state->ss0.mag_filter = I965_MAPFILTER_LINEAR;
525     }
526
527     sampler_state->ss3.r_wrap_mode = I965_TEXCOORDMODE_CLAMP;
528     sampler_state->ss3.s_wrap_mode = I965_TEXCOORDMODE_CLAMP;
529     sampler_state->ss3.t_wrap_mode = I965_TEXCOORDMODE_CLAMP;
530
531     dri_bo_unmap(gpe_context->sampler.bo);
532 }
533
534 void
535 gen9_post_processing_context_init(VADriverContextP ctx,
536                                   void *data,
537                                   struct intel_batchbuffer *batch)
538 {
539     struct i965_driver_data *i965 = i965_driver_data(ctx);
540     struct i965_post_processing_context *pp_context = data;
541     struct i965_gpe_context *gpe_context;
542
543     gen8_post_processing_context_common_init(ctx, data, pp_modules_gen9, ARRAY_ELEMS(pp_modules_gen9), batch);
544     avs_init_state(&pp_context->pp_avs_context.state, &gen9_avs_config);
545
546     pp_context->intel_post_processing = gen9_post_processing;
547
548     gpe_context = &pp_context->scaling_gpe_context;
549     gen8_gpe_load_kernels(ctx, gpe_context, pp_common_scaling_gen9, ARRAY_ELEMS(pp_common_scaling_gen9));
550     gpe_context->idrt.entry_size = ALIGN(sizeof(struct gen8_interface_descriptor_data), 64);
551     gpe_context->idrt.max_entries = ALIGN(ARRAY_ELEMS(pp_common_scaling_gen9), 2);
552     gpe_context->sampler.entry_size = ALIGN(sizeof(struct gen8_sampler_state), 64);
553     gpe_context->sampler.max_entries = 1;
554     gpe_context->curbe.length = ALIGN(sizeof(struct scaling_input_parameter), 64);
555
556     gpe_context->surface_state_binding_table.max_entries = MAX_SCALING_SURFACES;
557     gpe_context->surface_state_binding_table.binding_table_offset = 0;
558     gpe_context->surface_state_binding_table.surface_state_offset = ALIGN(MAX_SCALING_SURFACES * 4, 64);
559     gpe_context->surface_state_binding_table.length = ALIGN(MAX_SCALING_SURFACES * 4, 64) + ALIGN(MAX_SCALING_SURFACES * SURFACE_STATE_PADDED_SIZE_GEN9, 64);
560
561     if (i965->intel.eu_total > 0) {
562         gpe_context->vfe_state.max_num_threads = i965->intel.eu_total * 6;
563     } else {
564         if (i965->intel.has_bsd2)
565             gpe_context->vfe_state.max_num_threads = 300;
566         else
567             gpe_context->vfe_state.max_num_threads = 60;
568     }
569
570     gpe_context->vfe_state.curbe_allocation_size = 37;
571     gpe_context->vfe_state.urb_entry_size = 16;
572     gpe_context->vfe_state.num_urb_entries = 127;
573     gpe_context->vfe_state.gpgpu_mode = 0;
574
575     gen8_gpe_context_init(ctx, gpe_context);
576     pp_context->scaling_gpe_context_initialized |= (VPPGPE_8BIT_8BIT | VPPGPE_10BIT_10BIT | VPPGPE_10BIT_8BIT | VPPGPE_8BIT_420_RGB32);
577
578     return;
579 }
580
581 static void
582 gen9_add_dri_buffer_2d_gpe_surface(VADriverContextP ctx,
583                                    struct i965_gpe_context *gpe_context,
584                                    dri_bo *bo,
585                                    unsigned int bo_offset,
586                                    unsigned int width,
587                                    unsigned int height,
588                                    unsigned int pitch,
589                                    int is_media_block_rw,
590                                    unsigned int format,
591                                    int index,
592                                    int is_16bit)
593 {
594     struct i965_gpe_resource gpe_resource;
595     struct i965_gpe_surface gpe_surface;
596
597     i965_dri_object_to_2d_gpe_resource(&gpe_resource, bo, width, height, pitch);
598     memset(&gpe_surface, 0, sizeof(gpe_surface));
599     gpe_surface.gpe_resource = &gpe_resource;
600     gpe_surface.is_2d_surface = 1;
601     gpe_surface.is_media_block_rw = !!is_media_block_rw;
602     gpe_surface.cacheability_control = DEFAULT_MOCS;
603     gpe_surface.format = format;
604     gpe_surface.is_override_offset = 1;
605     gpe_surface.offset = bo_offset;
606     gpe_surface.is_16bpp = is_16bit;
607
608     gen9_gpe_context_add_surface(gpe_context, &gpe_surface, index);
609
610     i965_free_gpe_resource(&gpe_resource);
611 }
612
613 static void
614 gen9_run_kernel_media_object_walker(VADriverContextP ctx,
615                                     struct intel_batchbuffer *batch,
616                                     struct i965_gpe_context *gpe_context,
617                                     struct gpe_media_object_walker_parameter *param)
618 {
619     if (!batch || !gpe_context || !param)
620         return;
621
622     intel_batchbuffer_start_atomic(batch, 0x1000);
623
624     intel_batchbuffer_emit_mi_flush(batch);
625
626     gen9_gpe_pipeline_setup(ctx, gpe_context, batch);
627     gen8_gpe_media_object_walker(ctx, gpe_context, batch, param);
628     gen8_gpe_media_state_flush(ctx, gpe_context, batch);
629
630     gen9_gpe_pipeline_end(ctx, gpe_context, batch);
631
632     intel_batchbuffer_end_atomic(batch);
633
634     intel_batchbuffer_flush(batch);
635     return;
636 }
637
638 static void
639 gen9_gpe_context_p010_scaling_curbe(VADriverContextP ctx,
640                                     struct i965_gpe_context *gpe_context,
641                                     VARectangle *src_rect,
642                                     struct i965_surface *src_surface,
643                                     VARectangle *dst_rect,
644                                     struct i965_surface *dst_surface)
645 {
646     struct scaling_input_parameter *scaling_curbe;
647     float src_width, src_height;
648     float coeff;
649     unsigned int fourcc;
650
651     if ((gpe_context == NULL) ||
652         (src_rect == NULL) || (src_surface == NULL) ||
653         (dst_rect == NULL) || (dst_surface == NULL))
654         return;
655
656     scaling_curbe = i965_gpe_context_map_curbe(gpe_context);
657
658     if (!scaling_curbe)
659         return;
660
661     memset(scaling_curbe, 0, sizeof(struct scaling_input_parameter));
662
663     scaling_curbe->bti_input = BTI_SCALING_INPUT_Y;
664     scaling_curbe->bti_output = BTI_SCALING_OUTPUT_Y;
665
666     /* As the src_rect/dst_rect is already checked, it is skipped.*/
667     scaling_curbe->x_dst     = dst_rect->x;
668     scaling_curbe->y_dst     = dst_rect->y;
669
670     src_width = src_rect->x + src_rect->width;
671     src_height = src_rect->y + src_rect->height;
672
673     scaling_curbe->inv_width = 1 / src_width;
674     scaling_curbe->inv_height = 1 / src_height;
675
676     coeff = (float)(src_rect->width) / dst_rect->width;
677     scaling_curbe->x_factor = coeff / src_width;
678     scaling_curbe->x_orig = (float)(src_rect->x) / src_width;
679
680     coeff = (float)(src_rect->height) / dst_rect->height;
681     scaling_curbe->y_factor = coeff / src_height;
682     scaling_curbe->y_orig = (float)(src_rect->y) / src_height;
683
684     fourcc = pp_get_surface_fourcc(ctx, src_surface);
685     if (fourcc == VA_FOURCC_P010) {
686         scaling_curbe->dw2.src_packed = 1;
687         scaling_curbe->dw2.src_msb = 1;
688     }
689     /* I010 will use LSB */
690
691     fourcc = pp_get_surface_fourcc(ctx, dst_surface);
692
693     if (fourcc == VA_FOURCC_P010) {
694         scaling_curbe->dw2.dst_packed = 1;
695         scaling_curbe->dw2.dst_msb = 1;
696     }
697     /* I010 will use LSB */
698
699     i965_gpe_context_unmap_curbe(gpe_context);
700 }
701
702 static bool
703 gen9_pp_context_get_surface_conf(VADriverContextP ctx,
704                                  struct i965_surface *surface,
705                                  VARectangle *rect,
706                                  int *width,
707                                  int *height,
708                                  int *pitch,
709                                  int *bo_offset)
710 {
711     unsigned int fourcc;
712     if (!rect || !surface || !width || !height || !pitch || !bo_offset)
713         return false;
714
715     if (surface->base == NULL)
716         return false;
717
718     fourcc = pp_get_surface_fourcc(ctx, surface);
719     if (surface->type == I965_SURFACE_TYPE_SURFACE) {
720         struct object_surface *obj_surface;
721
722         obj_surface = (struct object_surface *)surface->base;
723         width[0] = MIN(rect->x + rect->width, obj_surface->orig_width);
724         height[0] = MIN(rect->y + rect->height, obj_surface->orig_height);
725         pitch[0] = obj_surface->width;
726         bo_offset[0] = 0;
727
728         if (fourcc == VA_FOURCC_RGBX ||
729             fourcc == VA_FOURCC_RGBA ||
730             fourcc == VA_FOURCC_BGRX ||
731             fourcc == VA_FOURCC_BGRA) {
732             /* nothing to do here */
733         } else if (fourcc == VA_FOURCC_P010 || fourcc == VA_FOURCC_NV12) {
734             width[1] = width[0] / 2;
735             height[1] = height[0] / 2;
736             pitch[1] = obj_surface->cb_cr_pitch;
737             bo_offset[1] = obj_surface->width * obj_surface->y_cb_offset;
738         } else if (fourcc == VA_FOURCC_YUY2 || fourcc == VA_FOURCC_UYVY) {
739             /* nothing to do here */
740         } else {
741             width[1] = width[0] / 2;
742             height[1] = height[0] / 2;
743             pitch[1] = obj_surface->cb_cr_pitch;
744             bo_offset[1] = obj_surface->width * obj_surface->y_cb_offset;
745             width[2] = width[0] / 2;
746             height[2] = height[0] / 2;
747             pitch[2] = obj_surface->cb_cr_pitch;
748             bo_offset[2] = obj_surface->width * obj_surface->y_cr_offset;
749         }
750
751     } else {
752         struct object_image *obj_image;
753
754         obj_image = (struct object_image *)surface->base;
755
756         width[0] = MIN(rect->x + rect->width, obj_image->image.width);
757         height[0] = MIN(rect->y + rect->height, obj_image->image.height);
758         pitch[0] = obj_image->image.pitches[0];
759         bo_offset[0] = obj_image->image.offsets[0];
760
761         if (fourcc == VA_FOURCC_RGBX ||
762             fourcc == VA_FOURCC_RGBA ||
763             fourcc == VA_FOURCC_BGRX ||
764             fourcc == VA_FOURCC_BGRA) {
765             /* nothing to do here */
766         } else if (fourcc == VA_FOURCC_P010 || fourcc == VA_FOURCC_NV12) {
767             width[1] = width[0] / 2;
768             height[1] = height[0] / 2;
769             pitch[1] = obj_image->image.pitches[1];
770             bo_offset[1] = obj_image->image.offsets[1];
771         } else if (fourcc == VA_FOURCC_YUY2 || fourcc == VA_FOURCC_UYVY) {
772             /* nothing to do here */
773         } else {
774             int u = 1, v = 2;
775
776             if (fourcc == VA_FOURCC_YV12 || fourcc == VA_FOURCC_IMC1)
777                 u = 2, v = 1;
778
779             width[1] = width[0] / 2;
780             height[1] = height[0] / 2;
781             pitch[1] = obj_image->image.pitches[u];
782             bo_offset[1] = obj_image->image.offsets[u];
783             width[2] = width[0] / 2;
784             height[2] = height[0] / 2;
785             pitch[2] = obj_image->image.pitches[v];
786             bo_offset[2] = obj_image->image.offsets[v];
787         }
788
789     }
790
791     return true;
792 }
793
794 static void
795 gen9_gpe_context_p010_scaling_surfaces(VADriverContextP ctx,
796                                        struct i965_gpe_context *gpe_context,
797                                        VARectangle *src_rect,
798                                        struct i965_surface *src_surface,
799                                        VARectangle *dst_rect,
800                                        struct i965_surface *dst_surface)
801 {
802     unsigned int fourcc;
803     int width[3], height[3], pitch[3], bo_offset[3];
804     dri_bo *bo;
805     struct object_surface *obj_surface;
806     struct object_image *obj_image;
807     int bti;
808
809     if ((gpe_context == NULL) ||
810         (src_rect == NULL) || (src_surface == NULL) ||
811         (dst_rect == NULL) || (dst_surface == NULL))
812         return;
813
814     if (src_surface->base == NULL || dst_surface->base == NULL)
815         return;
816
817     fourcc = pp_get_surface_fourcc(ctx, src_surface);
818
819     if (src_surface->type == I965_SURFACE_TYPE_SURFACE) {
820         obj_surface = (struct object_surface *)src_surface->base;
821         bo = obj_surface->bo;
822     } else {
823         obj_image = (struct object_image *)src_surface->base;
824         bo = obj_image->bo;
825     }
826
827     bti = 0;
828     if (gen9_pp_context_get_surface_conf(ctx, src_surface, src_rect,
829                                          width, height, pitch,
830                                          bo_offset)) {
831         bti = BTI_SCALING_INPUT_Y;
832         /* Input surface */
833         gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
834                                            bo_offset[0],
835                                            width[0], height[0],
836                                            pitch[0], 0,
837                                            I965_SURFACEFORMAT_R16_UNORM,
838                                            bti, 1);
839         if (fourcc == VA_FOURCC_P010) {
840             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
841                                                bo_offset[1],
842                                                width[1], height[1],
843                                                pitch[1], 0,
844                                                I965_SURFACEFORMAT_R16G16_UNORM,
845                                                bti + 1, 1);
846         } else {
847             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
848                                                bo_offset[1],
849                                                width[1], height[1],
850                                                pitch[1], 0,
851                                                I965_SURFACEFORMAT_R16_UNORM,
852                                                bti + 1, 1);
853
854             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
855                                                bo_offset[2],
856                                                width[2], height[2],
857                                                pitch[2], 0,
858                                                I965_SURFACEFORMAT_R16_UNORM,
859                                                bti + 2, 1);
860         }
861     }
862
863     fourcc = pp_get_surface_fourcc(ctx, dst_surface);
864
865     if (dst_surface->type == I965_SURFACE_TYPE_SURFACE) {
866         obj_surface = (struct object_surface *)dst_surface->base;
867         bo = obj_surface->bo;
868     } else {
869         obj_image = (struct object_image *)dst_surface->base;
870         bo = obj_image->bo;
871     }
872
873     if (gen9_pp_context_get_surface_conf(ctx, dst_surface, dst_rect,
874                                          width, height, pitch,
875                                          bo_offset)) {
876         bti = BTI_SCALING_OUTPUT_Y;
877         /* Input surface */
878         gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
879                                            bo_offset[0],
880                                            width[0], height[0],
881                                            pitch[0], 1,
882                                            I965_SURFACEFORMAT_R16_UINT,
883                                            bti, 1);
884         if (fourcc == VA_FOURCC_P010) {
885             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
886                                                bo_offset[1],
887                                                width[1] * 2, height[1],
888                                                pitch[1], 1,
889                                                I965_SURFACEFORMAT_R16_UINT,
890                                                bti + 1, 1);
891         } else {
892             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
893                                                bo_offset[1],
894                                                width[1], height[1],
895                                                pitch[1], 1,
896                                                I965_SURFACEFORMAT_R16_UINT,
897                                                bti + 1, 1);
898
899             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
900                                                bo_offset[2],
901                                                width[2], height[2],
902                                                pitch[2], 1,
903                                                I965_SURFACEFORMAT_R16_UINT,
904                                                bti + 2, 1);
905         }
906     }
907
908     return;
909 }
910
911 VAStatus
912 gen9_p010_scaling_post_processing(
913     VADriverContextP   ctx,
914     struct i965_post_processing_context *pp_context,
915     struct i965_surface *src_surface,
916     VARectangle *src_rect,
917     struct i965_surface *dst_surface,
918     VARectangle *dst_rect)
919 {
920     struct i965_gpe_context *gpe_context;
921     struct gpe_media_object_walker_parameter media_object_walker_param;
922     struct intel_vpp_kernel_walker_parameter kernel_walker_param;
923
924     if (!pp_context || !src_surface || !src_rect || !dst_surface || !dst_rect)
925         return VA_STATUS_ERROR_INVALID_PARAMETER;
926
927     if (!(pp_context->scaling_gpe_context_initialized & VPPGPE_10BIT_10BIT))
928         return VA_STATUS_ERROR_UNIMPLEMENTED;
929
930     gpe_context = &pp_context->scaling_gpe_context;
931
932     gen8_gpe_context_init(ctx, gpe_context);
933     gen9_vpp_scaling_sample_state(ctx, gpe_context, src_rect, dst_rect);
934     gen9_gpe_reset_binding_table(ctx, gpe_context);
935     gen9_gpe_context_p010_scaling_curbe(ctx, gpe_context,
936                                         src_rect, src_surface,
937                                         dst_rect, dst_surface);
938
939     gen9_gpe_context_p010_scaling_surfaces(ctx, gpe_context,
940                                            src_rect, src_surface,
941                                            dst_rect, dst_surface);
942
943     gen8_gpe_setup_interface_data(ctx, gpe_context);
944
945     memset(&kernel_walker_param, 0, sizeof(kernel_walker_param));
946     kernel_walker_param.resolution_x = ALIGN(dst_rect->width, 16) >> 4;
947     kernel_walker_param.resolution_y = ALIGN(dst_rect->height, 16) >> 4;
948     kernel_walker_param.no_dependency = 1;
949
950     intel_vpp_init_media_object_walker_parameter(&kernel_walker_param, &media_object_walker_param);
951     media_object_walker_param.interface_offset = 0;
952     gen9_run_kernel_media_object_walker(ctx, pp_context->batch,
953                                         gpe_context,
954                                         &media_object_walker_param);
955
956     return VA_STATUS_SUCCESS;
957 }
958
959 static void
960 gen9_gpe_context_yuv420p8_scaling_curbe(VADriverContextP ctx,
961                                         struct i965_gpe_context *gpe_context,
962                                         VARectangle *src_rect,
963                                         struct i965_surface *src_surface,
964                                         VARectangle *dst_rect,
965                                         struct i965_surface *dst_surface)
966 {
967     struct scaling_input_parameter *scaling_curbe;
968     float src_width, src_height;
969     float coeff;
970     unsigned int fourcc;
971
972     if ((gpe_context == NULL) ||
973         (src_rect == NULL) || (src_surface == NULL) ||
974         (dst_rect == NULL) || (dst_surface == NULL))
975         return;
976
977     scaling_curbe = i965_gpe_context_map_curbe(gpe_context);
978
979     if (!scaling_curbe)
980         return;
981
982     memset(scaling_curbe, 0, sizeof(struct scaling_input_parameter));
983
984     scaling_curbe->bti_input = BTI_SCALING_INPUT_Y;
985     scaling_curbe->bti_output = BTI_SCALING_OUTPUT_Y;
986
987     /* As the src_rect/dst_rect is already checked, it is skipped.*/
988     scaling_curbe->x_dst     = dst_rect->x;
989     scaling_curbe->y_dst     = dst_rect->y;
990
991     src_width = src_rect->x + src_rect->width;
992     src_height = src_rect->y + src_rect->height;
993
994     scaling_curbe->inv_width = 1 / src_width;
995     scaling_curbe->inv_height = 1 / src_height;
996
997     coeff = (float)(src_rect->width) / dst_rect->width;
998     scaling_curbe->x_factor = coeff / src_width;
999     scaling_curbe->x_orig = (float)(src_rect->x) / src_width;
1000
1001     coeff = (float)(src_rect->height) / dst_rect->height;
1002     scaling_curbe->y_factor = coeff / src_height;
1003     scaling_curbe->y_orig = (float)(src_rect->y) / src_height;
1004
1005     fourcc = pp_get_surface_fourcc(ctx, src_surface);
1006     if (fourcc == VA_FOURCC_NV12) {
1007         scaling_curbe->dw2.src_packed = 1;
1008     }
1009
1010     fourcc = pp_get_surface_fourcc(ctx, dst_surface);
1011
1012     if (fourcc == VA_FOURCC_NV12) {
1013         scaling_curbe->dw2.dst_packed = 1;
1014     }
1015
1016     i965_gpe_context_unmap_curbe(gpe_context);
1017 }
1018
1019 static void
1020 gen9_gpe_context_yuv420p8_scaling_surfaces(VADriverContextP ctx,
1021                                            struct i965_gpe_context *gpe_context,
1022                                            VARectangle *src_rect,
1023                                            struct i965_surface *src_surface,
1024                                            VARectangle *dst_rect,
1025                                            struct i965_surface *dst_surface)
1026 {
1027     unsigned int fourcc;
1028     int width[3], height[3], pitch[3], bo_offset[3];
1029     dri_bo *bo;
1030     struct object_surface *obj_surface;
1031     struct object_image *obj_image;
1032     int bti;
1033
1034     if ((gpe_context == NULL) ||
1035         (src_rect == NULL) || (src_surface == NULL) ||
1036         (dst_rect == NULL) || (dst_surface == NULL))
1037         return;
1038
1039     if (src_surface->base == NULL || dst_surface->base == NULL)
1040         return;
1041
1042     fourcc = pp_get_surface_fourcc(ctx, src_surface);
1043
1044     if (src_surface->type == I965_SURFACE_TYPE_SURFACE) {
1045         obj_surface = (struct object_surface *)src_surface->base;
1046         bo = obj_surface->bo;
1047     } else {
1048         obj_image = (struct object_image *)src_surface->base;
1049         bo = obj_image->bo;
1050     }
1051
1052     bti = 0;
1053     if (gen9_pp_context_get_surface_conf(ctx, src_surface, src_rect,
1054                                          width, height, pitch,
1055                                          bo_offset)) {
1056         bti = BTI_SCALING_INPUT_Y;
1057         /* Input surface */
1058         gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1059                                            bo_offset[0],
1060                                            width[0], height[0],
1061                                            pitch[0], 0,
1062                                            I965_SURFACEFORMAT_R8_UNORM,
1063                                            bti, 0);
1064         if (fourcc == VA_FOURCC_NV12) {
1065             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1066                                                bo_offset[1],
1067                                                width[1], height[1],
1068                                                pitch[1], 0,
1069                                                I965_SURFACEFORMAT_R8G8_UNORM,
1070                                                bti + 1, 0);
1071         } else {
1072             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1073                                                bo_offset[1],
1074                                                width[1], height[1],
1075                                                pitch[1], 0,
1076                                                I965_SURFACEFORMAT_R8_UNORM,
1077                                                bti + 1, 0);
1078
1079             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1080                                                bo_offset[2],
1081                                                width[2], height[2],
1082                                                pitch[2], 0,
1083                                                I965_SURFACEFORMAT_R8_UNORM,
1084                                                bti + 2, 0);
1085         }
1086     }
1087
1088     fourcc = pp_get_surface_fourcc(ctx, dst_surface);
1089
1090     if (dst_surface->type == I965_SURFACE_TYPE_SURFACE) {
1091         obj_surface = (struct object_surface *)dst_surface->base;
1092         bo = obj_surface->bo;
1093     } else {
1094         obj_image = (struct object_image *)dst_surface->base;
1095         bo = obj_image->bo;
1096     }
1097
1098     if (gen9_pp_context_get_surface_conf(ctx, dst_surface, dst_rect,
1099                                          width, height, pitch,
1100                                          bo_offset)) {
1101         bti = BTI_SCALING_OUTPUT_Y;
1102         /* Input surface */
1103         gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1104                                            bo_offset[0],
1105                                            width[0], height[0],
1106                                            pitch[0], 1,
1107                                            I965_SURFACEFORMAT_R8_UINT,
1108                                            bti, 0);
1109         if (fourcc == VA_FOURCC_NV12) {
1110             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1111                                                bo_offset[1],
1112                                                width[1] * 2, height[1],
1113                                                pitch[1], 1,
1114                                                I965_SURFACEFORMAT_R16_UINT,
1115                                                bti + 1, 0);
1116         } else {
1117             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1118                                                bo_offset[1],
1119                                                width[1], height[1],
1120                                                pitch[1], 1,
1121                                                I965_SURFACEFORMAT_R8_UINT,
1122                                                bti + 1, 0);
1123
1124             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1125                                                bo_offset[2],
1126                                                width[2], height[2],
1127                                                pitch[2], 1,
1128                                                I965_SURFACEFORMAT_R8_UINT,
1129                                                bti + 2, 0);
1130         }
1131     }
1132
1133     return;
1134 }
1135
1136 VAStatus
1137 gen9_yuv420p8_scaling_post_processing(
1138     VADriverContextP   ctx,
1139     struct i965_post_processing_context *pp_context,
1140     struct i965_surface *src_surface,
1141     VARectangle *src_rect,
1142     struct i965_surface *dst_surface,
1143     VARectangle *dst_rect)
1144 {
1145     struct i965_gpe_context *gpe_context;
1146     struct gpe_media_object_walker_parameter media_object_walker_param;
1147     struct intel_vpp_kernel_walker_parameter kernel_walker_param;
1148
1149     if (!pp_context || !src_surface || !src_rect || !dst_surface || !dst_rect)
1150         return VA_STATUS_ERROR_INVALID_PARAMETER;
1151
1152     if (!(pp_context->scaling_gpe_context_initialized & VPPGPE_8BIT_8BIT))
1153         return VA_STATUS_ERROR_UNIMPLEMENTED;
1154
1155     gpe_context = &pp_context->scaling_gpe_context;
1156
1157     gen8_gpe_context_init(ctx, gpe_context);
1158     gen9_vpp_scaling_sample_state(ctx, gpe_context, src_rect, dst_rect);
1159     gen9_gpe_reset_binding_table(ctx, gpe_context);
1160     gen9_gpe_context_yuv420p8_scaling_curbe(ctx, gpe_context,
1161                                             src_rect, src_surface,
1162                                             dst_rect, dst_surface);
1163
1164     gen9_gpe_context_yuv420p8_scaling_surfaces(ctx, gpe_context,
1165                                                src_rect, src_surface,
1166                                                dst_rect, dst_surface);
1167
1168     gen8_gpe_setup_interface_data(ctx, gpe_context);
1169
1170     memset(&kernel_walker_param, 0, sizeof(kernel_walker_param));
1171     kernel_walker_param.resolution_x = ALIGN(dst_rect->width, 16) >> 4;
1172     kernel_walker_param.resolution_y = ALIGN(dst_rect->height, 16) >> 4;
1173     kernel_walker_param.no_dependency = 1;
1174
1175     intel_vpp_init_media_object_walker_parameter(&kernel_walker_param, &media_object_walker_param);
1176     media_object_walker_param.interface_offset = 1;
1177     gen9_run_kernel_media_object_walker(ctx, pp_context->batch,
1178                                         gpe_context,
1179                                         &media_object_walker_param);
1180
1181     return VA_STATUS_SUCCESS;
1182 }
1183
1184 static void
1185 gen9_gpe_context_10bit_8bit_scaling_curbe(VADriverContextP ctx,
1186                                           struct i965_gpe_context *gpe_context,
1187                                           VARectangle *src_rect,
1188                                           struct i965_surface *src_surface,
1189                                           VARectangle *dst_rect,
1190                                           struct i965_surface *dst_surface)
1191 {
1192     struct scaling_input_parameter *scaling_curbe;
1193     float src_width, src_height;
1194     float coeff;
1195     unsigned int fourcc;
1196     int src_format = SRC_FORMAT_P010, dst_format = DST_FORMAT_YUY2;
1197
1198     if ((gpe_context == NULL) ||
1199         (src_rect == NULL) || (src_surface == NULL) ||
1200         (dst_rect == NULL) || (dst_surface == NULL))
1201         return;
1202
1203     scaling_curbe = i965_gpe_context_map_curbe(gpe_context);
1204
1205     if (!scaling_curbe)
1206         return;
1207
1208     memset(scaling_curbe, 0, sizeof(struct scaling_input_parameter));
1209
1210     scaling_curbe->bti_input = BTI_SCALING_INPUT_Y;
1211     scaling_curbe->bti_output = BTI_SCALING_OUTPUT_Y;
1212
1213     /* As the src_rect/dst_rect is already checked, it is skipped.*/
1214     scaling_curbe->x_dst     = dst_rect->x;
1215     scaling_curbe->y_dst     = dst_rect->y;
1216
1217     src_width = src_rect->x + src_rect->width;
1218     src_height = src_rect->y + src_rect->height;
1219
1220     scaling_curbe->inv_width = 1 / src_width;
1221     scaling_curbe->inv_height = 1 / src_height;
1222
1223     coeff = (float)(src_rect->width) / dst_rect->width;
1224     scaling_curbe->x_factor = coeff / src_width;
1225     scaling_curbe->x_orig = (float)(src_rect->x) / src_width;
1226
1227     coeff = (float)(src_rect->height) / dst_rect->height;
1228     scaling_curbe->y_factor = coeff / src_height;
1229     scaling_curbe->y_orig = (float)(src_rect->y) / src_height;
1230
1231     fourcc = pp_get_surface_fourcc(ctx, src_surface);
1232
1233     switch (fourcc) {
1234     case VA_FOURCC_P010:
1235         src_format = SRC_FORMAT_P010;
1236         break;
1237
1238     case VA_FOURCC_I010:
1239         src_format = SRC_FORMAT_I010;
1240         break;
1241
1242     default:
1243         break;
1244     }
1245
1246     fourcc = pp_get_surface_fourcc(ctx, dst_surface);
1247
1248     switch (fourcc) {
1249     case VA_FOURCC_YUY2:
1250         dst_format = DST_FORMAT_YUY2;
1251         break;
1252
1253     case VA_FOURCC_UYVY:
1254         dst_format = DST_FORMAT_UYVY;
1255         break;
1256
1257     case VA_FOURCC_NV12:
1258         dst_format = DST_FORMAT_NV12;
1259         break;
1260
1261     case VA_FOURCC_I420:
1262     case VA_FOURCC_IMC3: /* pitch / base address is set via surface_state */
1263         dst_format = DST_FORMAT_I420;
1264         break;
1265
1266     case VA_FOURCC_YV12:
1267     case VA_FOURCC_IMC1: /* pitch / base address is set via surface_state */
1268         dst_format = DST_FORMAT_YV12;
1269         break;
1270
1271     default:
1272         break;
1273     }
1274
1275     scaling_curbe->dw2.src_format = src_format;
1276     scaling_curbe->dw2.dst_format = dst_format;
1277
1278     i965_gpe_context_unmap_curbe(gpe_context);
1279 }
1280
1281 static void
1282 gen9_gpe_context_10bit_8bit_scaling_surfaces(VADriverContextP ctx,
1283                                              struct i965_gpe_context *gpe_context,
1284                                              VARectangle *src_rect,
1285                                              struct i965_surface *src_surface,
1286                                              VARectangle *dst_rect,
1287                                              struct i965_surface *dst_surface)
1288 {
1289     unsigned int fourcc;
1290     int width[3], height[3], pitch[3], bo_offset[3];
1291     dri_bo *bo;
1292     struct object_surface *obj_surface;
1293     struct object_image *obj_image;
1294     int bti;
1295
1296     if ((gpe_context == NULL) ||
1297         (src_rect == NULL) || (src_surface == NULL) ||
1298         (dst_rect == NULL) || (dst_surface == NULL))
1299         return;
1300
1301     if (src_surface->base == NULL || dst_surface->base == NULL)
1302         return;
1303
1304     fourcc = pp_get_surface_fourcc(ctx, src_surface);
1305
1306     if (src_surface->type == I965_SURFACE_TYPE_SURFACE) {
1307         obj_surface = (struct object_surface *)src_surface->base;
1308         bo = obj_surface->bo;
1309     } else {
1310         obj_image = (struct object_image *)src_surface->base;
1311         bo = obj_image->bo;
1312     }
1313
1314     bti = 0;
1315     if (gen9_pp_context_get_surface_conf(ctx, src_surface, src_rect,
1316                                          width, height, pitch,
1317                                          bo_offset)) {
1318         bti = BTI_SCALING_INPUT_Y;
1319         /* Input surface */
1320         gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1321                                            bo_offset[0],
1322                                            width[0], height[0],
1323                                            pitch[0], 0,
1324                                            I965_SURFACEFORMAT_R16_UNORM,
1325                                            bti, 1);
1326         if (fourcc == VA_FOURCC_P010) {
1327             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1328                                                bo_offset[1],
1329                                                width[1], height[1],
1330                                                pitch[1], 0,
1331                                                I965_SURFACEFORMAT_R16G16_UNORM,
1332                                                bti + 1, 1);
1333         } else {
1334             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1335                                                bo_offset[1],
1336                                                width[1], height[1],
1337                                                pitch[1], 0,
1338                                                I965_SURFACEFORMAT_R16_UNORM,
1339                                                bti + 1, 1);
1340
1341             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1342                                                bo_offset[2],
1343                                                width[2], height[2],
1344                                                pitch[2], 0,
1345                                                I965_SURFACEFORMAT_R16_UNORM,
1346                                                bti + 2, 1);
1347         }
1348     }
1349
1350     fourcc = pp_get_surface_fourcc(ctx, dst_surface);
1351
1352     if (dst_surface->type == I965_SURFACE_TYPE_SURFACE) {
1353         obj_surface = (struct object_surface *)dst_surface->base;
1354         bo = obj_surface->bo;
1355     } else {
1356         obj_image = (struct object_image *)dst_surface->base;
1357         bo = obj_image->bo;
1358     }
1359
1360     if (gen9_pp_context_get_surface_conf(ctx, dst_surface, dst_rect,
1361                                          width, height, pitch,
1362                                          bo_offset)) {
1363         bti = BTI_SCALING_OUTPUT_Y;
1364         /* Output surface */
1365
1366         if (fourcc == VA_FOURCC_YUY2 || fourcc == VA_FOURCC_UYVY) {
1367             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1368                                                bo_offset[0],
1369                                                width[0] * 2, height[0],
1370                                                pitch[0], 1,
1371                                                I965_SURFACEFORMAT_R8_UINT,
1372                                                bti, 0);
1373         } else {
1374             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1375                                                bo_offset[0],
1376                                                width[0], height[0],
1377                                                pitch[0], 1,
1378                                                I965_SURFACEFORMAT_R8_UINT,
1379                                                bti, 0);
1380
1381             if (fourcc == VA_FOURCC_NV12) {
1382                 gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1383                                                    bo_offset[1],
1384                                                    width[1] * 2, height[1],
1385                                                    pitch[1], 1,
1386                                                    I965_SURFACEFORMAT_R16_UINT,
1387                                                    bti + 1, 0);
1388             } else {
1389                 gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1390                                                    bo_offset[1],
1391                                                    width[1], height[1],
1392                                                    pitch[1], 1,
1393                                                    I965_SURFACEFORMAT_R8_UINT,
1394                                                    bti + 1, 0);
1395
1396                 gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1397                                                    bo_offset[2],
1398                                                    width[2], height[2],
1399                                                    pitch[2], 1,
1400                                                    I965_SURFACEFORMAT_R8_UINT,
1401                                                    bti + 2, 0);
1402             }
1403         }
1404     }
1405 }
1406
1407 VAStatus
1408 gen9_10bit_8bit_scaling_post_processing(VADriverContextP   ctx,
1409                                         struct i965_post_processing_context *pp_context,
1410                                         struct i965_surface *src_surface,
1411                                         VARectangle *src_rect,
1412                                         struct i965_surface *dst_surface,
1413                                         VARectangle *dst_rect)
1414 {
1415     struct i965_gpe_context *gpe_context;
1416     struct gpe_media_object_walker_parameter media_object_walker_param;
1417     struct intel_vpp_kernel_walker_parameter kernel_walker_param;
1418
1419     if (!pp_context || !src_surface || !src_rect || !dst_surface || !dst_rect)
1420         return VA_STATUS_ERROR_INVALID_PARAMETER;
1421
1422     if (!(pp_context->scaling_gpe_context_initialized & VPPGPE_10BIT_10BIT))
1423         return VA_STATUS_ERROR_UNIMPLEMENTED;
1424
1425     gpe_context = &pp_context->scaling_gpe_context;
1426
1427     gen8_gpe_context_init(ctx, gpe_context);
1428     gen9_vpp_scaling_sample_state(ctx, gpe_context, src_rect, dst_rect);
1429     gen9_gpe_reset_binding_table(ctx, gpe_context);
1430     gen9_gpe_context_10bit_8bit_scaling_curbe(ctx, gpe_context,
1431                                               src_rect, src_surface,
1432                                               dst_rect, dst_surface);
1433
1434     gen9_gpe_context_10bit_8bit_scaling_surfaces(ctx, gpe_context,
1435                                                  src_rect, src_surface,
1436                                                  dst_rect, dst_surface);
1437
1438     gen8_gpe_setup_interface_data(ctx, gpe_context);
1439
1440     memset(&kernel_walker_param, 0, sizeof(kernel_walker_param));
1441     kernel_walker_param.resolution_x = ALIGN(dst_rect->width, 16) >> 4;
1442     kernel_walker_param.resolution_y = ALIGN(dst_rect->height, 16) >> 4;
1443     kernel_walker_param.no_dependency = 1;
1444
1445     intel_vpp_init_media_object_walker_parameter(&kernel_walker_param, &media_object_walker_param);
1446     media_object_walker_param.interface_offset = 2;
1447     gen9_run_kernel_media_object_walker(ctx, pp_context->batch,
1448                                         gpe_context,
1449                                         &media_object_walker_param);
1450
1451     return VA_STATUS_SUCCESS;
1452 }
1453
1454 static void
1455 gen9_gpe_context_8bit_420_rgb32_scaling_curbe(VADriverContextP ctx,
1456                                               struct i965_gpe_context *gpe_context,
1457                                               VARectangle *src_rect,
1458                                               struct i965_surface *src_surface,
1459                                               VARectangle *dst_rect,
1460                                               struct i965_surface *dst_surface)
1461 {
1462     struct scaling_input_parameter *scaling_curbe;
1463     float src_width, src_height;
1464     float coeff;
1465     unsigned int fourcc;
1466     int src_format = SRC_FORMAT_I420, dst_format = DST_FORMAT_RGBX;
1467     const float * yuv_to_rgb_coefs;
1468     size_t yuv_to_rgb_coefs_size;
1469
1470     if ((gpe_context == NULL) ||
1471         (src_rect == NULL) || (src_surface == NULL) ||
1472         (dst_rect == NULL) || (dst_surface == NULL))
1473         return;
1474
1475     scaling_curbe = i965_gpe_context_map_curbe(gpe_context);
1476
1477     if (!scaling_curbe)
1478         return;
1479
1480     memset(scaling_curbe, 0, sizeof(struct scaling_input_parameter));
1481
1482     scaling_curbe->bti_input = BTI_SCALING_INPUT_Y;
1483     scaling_curbe->bti_output = BTI_SCALING_OUTPUT_Y;
1484
1485     /* As the src_rect/dst_rect is already checked, it is skipped.*/
1486     scaling_curbe->x_dst     = dst_rect->x;
1487     scaling_curbe->y_dst     = dst_rect->y;
1488
1489     src_width = src_rect->x + src_rect->width;
1490     src_height = src_rect->y + src_rect->height;
1491
1492     scaling_curbe->inv_width = 1 / src_width;
1493     scaling_curbe->inv_height = 1 / src_height;
1494
1495     coeff = (float)(src_rect->width) / dst_rect->width;
1496     scaling_curbe->x_factor = coeff / src_width;
1497     scaling_curbe->x_orig = (float)(src_rect->x) / src_width;
1498
1499     coeff = (float)(src_rect->height) / dst_rect->height;
1500     scaling_curbe->y_factor = coeff / src_height;
1501     scaling_curbe->y_orig = (float)(src_rect->y) / src_height;
1502
1503     fourcc = pp_get_surface_fourcc(ctx, src_surface);
1504
1505     switch (fourcc) {
1506     case VA_FOURCC_I420:
1507     case VA_FOURCC_IMC3: /* pitch / base address is set via surface_state */
1508         src_format = SRC_FORMAT_I420;
1509         break;
1510
1511     case VA_FOURCC_NV12:
1512         src_format = SRC_FORMAT_NV12;
1513         break;
1514
1515     case VA_FOURCC_YV12:
1516     case VA_FOURCC_IMC1: /* pitch / base address is set via surface_state */
1517         src_format = SRC_FORMAT_YV12;
1518         break;
1519
1520     default:
1521         break;
1522     }
1523
1524     fourcc = pp_get_surface_fourcc(ctx, dst_surface);
1525
1526     switch (fourcc) {
1527     case VA_FOURCC_RGBX:
1528         dst_format = DST_FORMAT_RGBX;
1529         break;
1530
1531     case VA_FOURCC_RGBA:
1532         dst_format = DST_FORMAT_RGBA;
1533         break;
1534
1535     case VA_FOURCC_BGRX:
1536         dst_format = DST_FORMAT_BGRX;
1537         break;
1538
1539     case VA_FOURCC_BGRA:
1540         dst_format = DST_FORMAT_BGRA;
1541         break;
1542
1543     default:
1544         break;
1545     }
1546
1547     scaling_curbe->dw2.src_format = src_format;
1548     scaling_curbe->dw2.dst_format = dst_format;
1549
1550     yuv_to_rgb_coefs = i915_color_standard_to_coefs(i915_filter_to_color_standard(src_surface->flags & VA_SRC_COLOR_MASK), &yuv_to_rgb_coefs_size);
1551     memcpy(&scaling_curbe->coef_ry, yuv_to_rgb_coefs, yuv_to_rgb_coefs_size);
1552
1553     i965_gpe_context_unmap_curbe(gpe_context);
1554 }
1555
1556 static void
1557 gen9_gpe_context_8bit_420_rgb32_scaling_surfaces(VADriverContextP ctx,
1558                                                  struct i965_gpe_context *gpe_context,
1559                                                  VARectangle *src_rect,
1560                                                  struct i965_surface *src_surface,
1561                                                  VARectangle *dst_rect,
1562                                                  struct i965_surface *dst_surface)
1563 {
1564     unsigned int fourcc;
1565     int width[3], height[3], pitch[3], bo_offset[3];
1566     dri_bo *bo;
1567     struct object_surface *obj_surface;
1568     struct object_image *obj_image;
1569     int bti;
1570
1571     if ((gpe_context == NULL) ||
1572         (src_rect == NULL) || (src_surface == NULL) ||
1573         (dst_rect == NULL) || (dst_surface == NULL))
1574         return;
1575
1576     if (src_surface->base == NULL || dst_surface->base == NULL)
1577         return;
1578
1579     fourcc = pp_get_surface_fourcc(ctx, src_surface);
1580
1581     if (src_surface->type == I965_SURFACE_TYPE_SURFACE) {
1582         obj_surface = (struct object_surface *)src_surface->base;
1583         bo = obj_surface->bo;
1584     } else {
1585         obj_image = (struct object_image *)src_surface->base;
1586         bo = obj_image->bo;
1587     }
1588
1589     if (gen9_pp_context_get_surface_conf(ctx, src_surface, src_rect,
1590                                          width, height, pitch,
1591                                          bo_offset)) {
1592         /* Input surface */
1593         bti = BTI_SCALING_INPUT_Y;
1594         gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1595                                            bo_offset[0],
1596                                            width[0], height[0],
1597                                            pitch[0], 0,
1598                                            I965_SURFACEFORMAT_R8_UNORM,
1599                                            bti, 0);
1600
1601         if (fourcc == VA_FOURCC_NV12) {
1602             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1603                                                bo_offset[1],
1604                                                width[1], height[1],
1605                                                pitch[1], 0,
1606                                                I965_SURFACEFORMAT_R8G8_UNORM,
1607                                                bti + 1, 0);
1608         } else {
1609             /* The corresponding shader handles U, V plane in order */
1610             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1611                                                bo_offset[1],
1612                                                width[1], height[1],
1613                                                pitch[1], 0,
1614                                                I965_SURFACEFORMAT_R8_UNORM,
1615                                                bti + 1, 0);
1616
1617             gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1618                                                bo_offset[2],
1619                                                width[2], height[2],
1620                                                pitch[2], 0,
1621                                                I965_SURFACEFORMAT_R8_UNORM,
1622                                                bti + 2, 0);
1623         }
1624     }
1625
1626     fourcc = pp_get_surface_fourcc(ctx, dst_surface);
1627
1628     if (dst_surface->type == I965_SURFACE_TYPE_SURFACE) {
1629         obj_surface = (struct object_surface *)dst_surface->base;
1630         bo = obj_surface->bo;
1631     } else {
1632         obj_image = (struct object_image *)dst_surface->base;
1633         bo = obj_image->bo;
1634     }
1635
1636     if (gen9_pp_context_get_surface_conf(ctx, dst_surface, dst_rect,
1637                                          width, height, pitch,
1638                                          bo_offset)) {
1639         assert(fourcc == VA_FOURCC_RGBX ||
1640                fourcc == VA_FOURCC_RGBA ||
1641                fourcc == VA_FOURCC_BGRX ||
1642                fourcc == VA_FOURCC_BGRA);
1643         assert(width[0] * 4 <= pitch[0]);
1644
1645         /* output surface */
1646         bti = BTI_SCALING_OUTPUT_Y;
1647         gen9_add_dri_buffer_2d_gpe_surface(ctx, gpe_context, bo,
1648                                            bo_offset[0],
1649                                            width[0] * 4, height[0],
1650                                            pitch[0], 1,
1651                                            I965_SURFACEFORMAT_R8_UINT,
1652                                            bti, 0);
1653     }
1654 }
1655
1656 VAStatus
1657 gen9_8bit_420_rgb32_scaling_post_processing(VADriverContextP   ctx,
1658                                             struct i965_post_processing_context *pp_context,
1659                                             struct i965_surface *src_surface,
1660                                             VARectangle *src_rect,
1661                                             struct i965_surface *dst_surface,
1662                                             VARectangle *dst_rect)
1663 {
1664     struct i965_gpe_context *gpe_context;
1665     struct gpe_media_object_walker_parameter media_object_walker_param;
1666     struct intel_vpp_kernel_walker_parameter kernel_walker_param;
1667
1668     if (!pp_context || !src_surface || !src_rect || !dst_surface || !dst_rect)
1669         return VA_STATUS_ERROR_INVALID_PARAMETER;
1670
1671     if (!(pp_context->scaling_gpe_context_initialized & VPPGPE_8BIT_420_RGB32))
1672         return VA_STATUS_ERROR_UNIMPLEMENTED;
1673
1674     gpe_context = &pp_context->scaling_gpe_context;
1675
1676     gen8_gpe_context_init(ctx, gpe_context);
1677     gen9_vpp_scaling_sample_state(ctx, gpe_context, src_rect, dst_rect);
1678     gen9_gpe_reset_binding_table(ctx, gpe_context);
1679     gen9_gpe_context_8bit_420_rgb32_scaling_curbe(ctx, gpe_context,
1680                                                   src_rect, src_surface,
1681                                                   dst_rect, dst_surface);
1682
1683     gen9_gpe_context_8bit_420_rgb32_scaling_surfaces(ctx, gpe_context,
1684                                                      src_rect, src_surface,
1685                                                      dst_rect, dst_surface);
1686
1687     gen8_gpe_setup_interface_data(ctx, gpe_context);
1688
1689     memset(&kernel_walker_param, 0, sizeof(kernel_walker_param));
1690     kernel_walker_param.resolution_x = ALIGN(dst_rect->width, 16) >> 4;
1691     kernel_walker_param.resolution_y = ALIGN(dst_rect->height, 16) >> 4;
1692     kernel_walker_param.no_dependency = 1;
1693
1694     intel_vpp_init_media_object_walker_parameter(&kernel_walker_param, &media_object_walker_param);
1695     media_object_walker_param.interface_offset = 3;
1696     gen9_run_kernel_media_object_walker(ctx, pp_context->batch,
1697                                         gpe_context,
1698                                         &media_object_walker_param);
1699
1700     return VA_STATUS_SUCCESS;
1701 }