Ps3GpuTransferData cannot handle negative X and Y copy directions, fallback to softwa...
[ps3freebsd_xf86_video_ps3gpu.git] / src / ps3gpu_cursor.c
blobd9f65320d03dcd8c22970a8e10d209c0b9cb489f
1 /*-
2 * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD$
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #include "xf86.h"
34 #include "xf86_OSproc.h"
36 #include "xf86Cursor.h"
37 #ifdef ARGB_CURSOR
38 #include "cursorstr.h"
39 #endif
41 #include "exa.h"
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <sys/uio.h>
46 #include <sys/ioctl.h>
47 #include <sys/mman.h>
48 #include <fcntl.h>
49 #include <unistd.h>
51 #include "ps3gpu_ctl.h"
53 #include "ps3gpu.h"
54 #include "ps3gpu_cursor.h"
56 #define PS3GPU_CURSOR_WIDTH 64
57 #define PS3GPU_CURSOR_HEIGHT 64
59 static Bool
60 Ps3GpuCursorEnable(ScrnInfoPtr pScrn, Bool enable)
62 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
63 struct ps3gpu_ctl_cursor_enable cursorEnable;
64 int err;
66 cursorEnable.context_id = gPtr->gpuContextId;
67 cursorEnable.head = PS3GPU_CTL_HEAD_A;
68 cursorEnable.enable = enable ? 1 : 0;
70 err = ioctl(gPtr->fd, PS3GPU_CTL_CURSOR_ENABLE,
71 &cursorEnable);
72 if (err) {
73 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
74 "Failed to %s cursor for head A\n",
75 enable ? "enable" : "disable");
76 return (FALSE);
79 cursorEnable.context_id = gPtr->gpuContextId;
80 cursorEnable.head = PS3GPU_CTL_HEAD_B;
81 cursorEnable.enable = enable ? 1 : 0;
83 err = ioctl(gPtr->fd, PS3GPU_CTL_CURSOR_ENABLE,
84 &cursorEnable);
85 if (err) {
86 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
87 "Failed to %s cursor for head B\n",
88 enable ? "enable" : "disable");
89 return (FALSE);
92 return (TRUE);
95 static Bool
96 Ps3GpuUseHWCursor(ScreenPtr pScreen, CursorPtr pCursor)
98 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
99 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
101 if (pCursor->bits->width > gPtr->cursorInfo->MaxWidth ||
102 pCursor->bits->height > gPtr->cursorInfo->MaxHeight)
103 return (FALSE);
105 gPtr->cursorWidth = pCursor->bits->width;
106 gPtr->cursorHeight = pCursor->bits->height;
108 return (TRUE);
111 static void
112 Ps3GpuSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
114 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
116 gPtr->cursorBgColor = 0xff000000 | bg;
117 gPtr->cursorFgColor = 0xff000000 | fg;
120 static void
121 Ps3GpuLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
123 #define BIT(p, x) ((p)[(x) >> 5] & (1 << (31 - ((x) & 0x1f))))
125 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
126 int size = gPtr->cursorInfo->MaxWidth * gPtr->cursorInfo->MaxHeight;
127 CARD32 *pSrc = (CARD32 *) src;
128 CARD32 *pMask = pSrc + (size >> 5);
129 CARD32 *pDst = (CARD32 *) gPtr->cursorBase;
130 int x, y;
132 if (gPtr->cursorShow) {
133 if (!Ps3GpuCursorEnable(pScrn, FALSE))
134 return;
137 memset(pDst, 0, size * sizeof(CARD32));
139 for (y = 0; y < gPtr->cursorHeight; y++) {
140 for (x = 0; x < gPtr->cursorWidth; x++) {
141 if (BIT(pMask, x)) {
142 if (BIT(pSrc, x))
143 pDst[x] = gPtr->cursorFgColor;
144 else
145 pDst[x] = gPtr->cursorBgColor;
149 pSrc += gPtr->cursorInfo->MaxWidth >> 5;
150 pMask += gPtr->cursorInfo->MaxWidth >> 5;
151 pDst += gPtr->cursorInfo->MaxWidth;
154 if (gPtr->cursorShow) {
155 if (!Ps3GpuCursorEnable(pScrn, TRUE))
156 return;
159 #undef BIT
162 static void
163 Ps3GpuSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
165 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
166 struct ps3gpu_ctl_cursor_set_position cursorSetPosition;
167 int err;
169 if (gPtr->cursorShow) {
170 if (!Ps3GpuCursorEnable(pScrn, FALSE))
171 return;
174 cursorSetPosition.context_id = gPtr->gpuContextId;
175 cursorSetPosition.head = PS3GPU_CTL_HEAD_A;
176 cursorSetPosition.x = x;
177 cursorSetPosition.y = y;
179 err = ioctl(gPtr->fd, PS3GPU_CTL_CURSOR_SET_POSITION,
180 &cursorSetPosition);
181 if (err) {
182 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
183 "Failed to set cursor position for head A\n");
186 cursorSetPosition.context_id = gPtr->gpuContextId;
187 cursorSetPosition.head = PS3GPU_CTL_HEAD_B;
188 cursorSetPosition.x = x;
189 cursorSetPosition.y = y;
191 err = ioctl(gPtr->fd, PS3GPU_CTL_CURSOR_SET_POSITION,
192 &cursorSetPosition);
193 if (err) {
194 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
195 "Failed to set cursor position for head B\n");
198 if (gPtr->cursorShow) {
199 if (!Ps3GpuCursorEnable(pScrn, TRUE))
200 return;
204 static void
205 Ps3GpuShowCursor(ScrnInfoPtr pScrn)
207 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
209 if (!Ps3GpuCursorEnable(pScrn, TRUE))
210 return;
212 gPtr->cursorShow = TRUE;
215 static void
216 Ps3GpuHideCursor(ScrnInfoPtr pScrn)
218 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
220 if (!Ps3GpuCursorEnable(pScrn, FALSE))
221 return;
223 gPtr->cursorShow = FALSE;
226 #ifdef ARGB_CURSOR
228 static Bool
229 Ps3GpuUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCursor)
231 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
232 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
234 if (pCursor->bits->width > gPtr->cursorInfo->MaxWidth ||
235 pCursor->bits->height > gPtr->cursorInfo->MaxHeight)
236 return (FALSE);
238 gPtr->cursorWidth = pCursor->bits->width;
239 gPtr->cursorHeight = pCursor->bits->height;
241 return (TRUE);
244 static void
245 Ps3GpuLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCursor)
247 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
248 int size = gPtr->cursorInfo->MaxWidth * gPtr->cursorInfo->MaxHeight;
249 CARD32 *pDst = (CARD32 *) gPtr->cursorBase;
250 CARD32 *pSrc = pCursor->bits->argb;
251 int x, y;
253 memset(pDst, 0, size * sizeof(CARD32));
255 for (y = 0; y < pCursor->bits->height; y++) {
256 for (x = 0; x < pCursor->bits->width; x++)
257 *pDst++ = *pSrc++;
261 #endif /* ARGB_CURSOR */
263 Bool
264 Ps3GpuCursorInit(ScreenPtr pScreen)
266 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
267 Ps3GpuPtr gPtr = PS3GPUPTR(pScrn);
268 xf86CursorInfoPtr cursorInfo;
269 struct ps3gpu_ctl_memory_allocate memoryAllocate;
270 struct ps3gpu_ctl_cursor_initialize cursorInitialize;
271 struct ps3gpu_ctl_cursor_set_image cursorSetImage;
272 int err;
274 gPtr->cursorSize = (PS3GPU_CURSOR_WIDTH *
275 PS3GPU_CURSOR_HEIGHT * sizeof(CARD32) +
276 ((1 << 12) - 1)) & ~((1 << 12) - 1);
278 memoryAllocate.context_id = gPtr->gpuContextId;
279 memoryAllocate.type = PS3GPU_CTL_MEMORY_TYPE_VIDEO;
280 memoryAllocate.size = gPtr->cursorSize;
281 memoryAllocate.align = 20;
283 err = ioctl(gPtr->fd, PS3GPU_CTL_MEMORY_ALLOCATE,
284 &memoryAllocate);
285 if (err) {
286 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
287 "Failed to allocate cursor memory\n");
288 return (FALSE);
291 gPtr->cursorHandle = memoryAllocate.handle;
293 gPtr->cursorBase = (pointer) mmap(NULL, gPtr->cursorSize,
294 PROT_READ | PROT_WRITE, MAP_SHARED, gPtr->fd,
295 gPtr->cursorHandle);
296 if (gPtr->cursorBase == (pointer *) MAP_FAILED) {
297 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
298 "Failed to map cursor memory\n");
299 return (FALSE);
302 cursorInitialize.context_id = gPtr->gpuContextId;
303 cursorInitialize.head = PS3GPU_CTL_HEAD_A;
305 err = ioctl(gPtr->fd, PS3GPU_CTL_CURSOR_INITIALIZE,
306 &cursorInitialize);
307 if (err) {
308 f86DrvMsg(pScrn->scrnIndex, X_ERROR,
309 "Failed to initialize cursor for head A\n");
310 return (FALSE);
313 cursorInitialize.context_id = gPtr->gpuContextId;
314 cursorInitialize.head = PS3GPU_CTL_HEAD_B;
316 err = ioctl(gPtr->fd, PS3GPU_CTL_CURSOR_INITIALIZE,
317 &cursorInitialize);
318 if (err) {
319 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
320 "Failed to initialize cursor for head B\n");
321 return (FALSE);
324 if (!Ps3GpuCursorEnable(pScrn, FALSE))
325 return (FALSE);
327 cursorSetImage.context_id = gPtr->gpuContextId;
328 cursorSetImage.head = PS3GPU_CTL_HEAD_A;
329 cursorSetImage.offset = gPtr->cursorHandle;
331 err = ioctl(gPtr->fd, PS3GPU_CTL_CURSOR_SET_IMAGE,
332 &cursorSetImage);
333 if (err) {
334 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
335 "Failed to set cursor image for head A\n");
336 return (FALSE);
339 cursorSetImage.context_id = gPtr->gpuContextId;
340 cursorSetImage.head = PS3GPU_CTL_HEAD_B;
341 cursorSetImage.offset = gPtr->cursorHandle;
343 err = ioctl(gPtr->fd, PS3GPU_CTL_CURSOR_SET_IMAGE,
344 &cursorSetImage);
345 if (err) {
346 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
347 "Failed to set cursor image for head B\n");
348 return (FALSE);
351 cursorInfo = xf86CreateCursorInfoRec();
352 if(!cursorInfo)
353 return (FALSE);
355 gPtr->cursorInfo = cursorInfo;
357 cursorInfo->MaxWidth = PS3GPU_CURSOR_WIDTH;
358 cursorInfo->MaxHeight = PS3GPU_CURSOR_HEIGHT;
359 cursorInfo->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
360 HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
362 cursorInfo->UseHWCursor = Ps3GpuUseHWCursor;
363 cursorInfo->SetCursorColors = Ps3GpuSetCursorColors;
364 cursorInfo->SetCursorPosition = Ps3GpuSetCursorPosition;
365 cursorInfo->LoadCursorImage = Ps3GpuLoadCursorImage;
366 cursorInfo->HideCursor = Ps3GpuHideCursor;
367 cursorInfo->ShowCursor = Ps3GpuShowCursor;
369 #ifdef ARGB_CURSOR
371 cursorInfo->Flags |= HARDWARE_CURSOR_ARGB;
373 cursorInfo->UseHWCursorARGB = Ps3GpuUseHWCursorARGB;
374 cursorInfo->LoadCursorARGB = Ps3GpuLoadCursorARGB;
376 #endif
378 return (xf86InitCursor(pScreen, cursorInfo));