Initial code release
[profile/ivi/xorg-x11-drv-intel.git] / src / intel_shadow.c
1 /**************************************************************************
2
3 Copyright 2010 Intel Corporation
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 above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
16 of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "xf86.h"
33 #include "xaarop.h"
34 #include "intel.h"
35 #include "i830_reg.h"
36
37 static dri_bo *
38 intel_shadow_create_bo(intel_screen_private *intel,
39                        int16_t x1, int16_t y1,
40                        int16_t x2, int16_t y2,
41                        int *pitch)
42 {
43         int w = x2 - x1, h = y2 - y1;
44         int size = h * w * intel->cpp;
45         dri_bo *bo;
46
47         bo = drm_intel_bo_alloc(intel->bufmgr, "shadow", size, 0);
48         if (bo && drm_intel_gem_bo_map_gtt(bo) == 0) {
49                 char *dst = bo->virtual;
50                 char *src = intel->shadow_buffer;
51                 int src_pitch = intel->shadow_stride;
52                 int row_length = w * intel->cpp;
53                 int num_rows = h;
54                 src += y1 * src_pitch + x1 * intel->cpp;
55                 do {
56                         memcpy (dst, src, row_length);
57                         src += src_pitch;
58                         dst += row_length;
59                 } while (--num_rows);
60                 drm_intel_gem_bo_unmap_gtt(bo);
61         }
62
63         *pitch = w * intel->cpp;
64         return bo;
65 }
66
67 static void intel_shadow_memcpy(intel_screen_private *intel)
68 {
69         char *src_data, *dst_data;
70         unsigned int src_pitch, dst_pitch;
71         RegionPtr region;
72         BoxPtr box;
73         int n;
74
75         if (drm_intel_gem_bo_map_gtt(intel->front_buffer))
76                 return;
77
78         src_data = intel->shadow_buffer;
79         dst_data = intel->front_buffer->virtual;
80
81         src_pitch = intel->shadow_stride;
82         dst_pitch = intel->front_pitch;
83
84         region = DamageRegion(intel->shadow_damage);
85         box = REGION_RECTS(region);
86         n = REGION_NUM_RECTS(region);
87         while (n--) {
88                 char *src = src_data + box->y1*src_pitch + box->x1*intel->cpp;
89                 char *dst = dst_data + box->y1*dst_pitch + box->x1*intel->cpp;
90                 int len = (box->x2 - box->x1)*intel->cpp;
91                 int row = box->y2 - box->y1;
92                 while (row--) {
93                         memcpy(dst, src, len);
94                         src += src_pitch;
95                         dst += dst_pitch;
96                 }
97                 box++;
98         }
99 }
100
101 void intel_shadow_blt(intel_screen_private *intel)
102 {
103         ScrnInfoPtr scrn = intel->scrn;
104         unsigned int dst_pitch;
105         uint32_t blt, br13;
106         RegionPtr region;
107         BoxPtr box;
108         int n;
109
110         /* Can we trust the BLT? Otherwise do an uncached mmecy. */
111         if (!intel->can_blt || IS_GEN2(intel)) {
112                 intel_shadow_memcpy(intel);
113                 return;
114         }
115
116         dst_pitch = intel->front_pitch;
117
118         blt = XY_SRC_COPY_BLT_CMD;
119         if (intel->cpp == 4)
120                 blt |= (XY_SRC_COPY_BLT_WRITE_ALPHA |
121                                 XY_SRC_COPY_BLT_WRITE_RGB);
122
123         if (INTEL_INFO(intel)->gen >= 40) {
124                 if (intel->front_tiling) {
125                         dst_pitch >>= 2;
126                         blt |= XY_SRC_COPY_BLT_DST_TILED;
127                 }
128         }
129
130         br13 = ROP_S << 16 | dst_pitch;
131         switch (intel->cpp) {
132                 default:
133                 case 4: br13 |= 1 << 25; /* RGB8888 */
134                 case 2: br13 |= 1 << 24; /* RGB565 */
135                 case 1: break;
136         }
137
138         region = DamageRegion(intel->shadow_damage);
139         box = REGION_RECTS(region);
140         n = REGION_NUM_RECTS(region);
141         while (n--) {
142                 int pitch;
143                 dri_bo *bo;
144
145                 bo = intel_shadow_create_bo(intel,
146                                             box->x1, box->y1,
147                                             box->x2, box->y2,
148                                             &pitch);
149                 if (bo == NULL)
150                         return;
151
152                 BEGIN_BATCH_BLT(8);
153                 OUT_BATCH(blt);
154                 OUT_BATCH(br13);
155                 OUT_BATCH(box->y1 << 16 | box->x1);
156                 OUT_BATCH(box->y2 << 16 | box->x2);
157                 OUT_RELOC_FENCED(intel->front_buffer,
158                                 I915_GEM_DOMAIN_RENDER,
159                                 I915_GEM_DOMAIN_RENDER,
160                                 0);
161                 OUT_BATCH(0);
162                 OUT_BATCH(pitch);
163                 OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER, 0, 0);
164
165                 ADVANCE_BATCH();
166
167                 drm_intel_bo_unreference(bo);
168                 box++;
169         }
170 }
171
172 void intel_shadow_create(struct intel_screen_private *intel)
173 {
174         ScrnInfoPtr scrn = intel->scrn;
175         ScreenPtr screen = scrn->pScreen;
176         PixmapPtr pixmap;
177         int stride;
178         void *buffer;
179
180         pixmap = screen->GetScreenPixmap(screen);
181         stride = intel->cpp*scrn->virtualX;
182         buffer = malloc(stride * scrn->virtualY);
183         if (buffer &&
184             screen->ModifyPixmapHeader(pixmap,
185                                        scrn->virtualX, scrn->virtualY,
186                                        -1, -1,
187                                        stride, buffer)) {
188                 free(intel->shadow_buffer);
189                 intel->shadow_buffer = buffer;
190         } else
191                 stride = intel->shadow_stride;
192
193         if (!intel->shadow_damage) {
194                 intel->shadow_damage =
195                         DamageCreate(NULL, NULL,
196                                      DamageReportNone, TRUE,
197                                      screen, intel);
198                 DamageRegister(&pixmap->drawable, intel->shadow_damage);
199                 DamageSetReportAfterOp(intel->shadow_damage, TRUE);
200         }
201
202         scrn->displayWidth = stride / intel->cpp;
203         intel->shadow_stride = stride;
204 }