diff options
Diffstat (limited to 'omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c')
-rw-r--r-- | omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c | 2863 |
1 files changed, 0 insertions, 2863 deletions
diff --git a/omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c b/omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c deleted file mode 100644 index d047c78..0000000 --- a/omap5/sgx_src/eurasia_km/services4/srvkm/common/deviceclass.c +++ /dev/null | |||
@@ -1,2863 +0,0 @@ | |||
1 | /*************************************************************************/ /*! | ||
2 | @Title Device class services functions | ||
3 | @Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved | ||
4 | @Description Kernel services functions for device class devices | ||
5 | @License Dual MIT/GPLv2 | ||
6 | |||
7 | The contents of this file are subject to the MIT license as set out below. | ||
8 | |||
9 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
10 | of this software and associated documentation files (the "Software"), to deal | ||
11 | in the Software without restriction, including without limitation the rights | ||
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
13 | copies of the Software, and to permit persons to whom the Software is | ||
14 | furnished to do so, subject to the following conditions: | ||
15 | |||
16 | The above copyright notice and this permission notice shall be included in | ||
17 | all copies or substantial portions of the Software. | ||
18 | |||
19 | Alternatively, the contents of this file may be used under the terms of | ||
20 | the GNU General Public License Version 2 ("GPL") in which case the provisions | ||
21 | of GPL are applicable instead of those above. | ||
22 | |||
23 | If you wish to allow use of your version of this file only under the terms of | ||
24 | GPL, and not to allow others to use your version of this file under the terms | ||
25 | of the MIT license, indicate your decision by deleting the provisions above | ||
26 | and replace them with the notice and other provisions required by GPL as set | ||
27 | out in the file called "GPL-COPYING" included in this distribution. If you do | ||
28 | not delete the provisions above, a recipient may use your version of this file | ||
29 | under the terms of either the MIT license or GPL. | ||
30 | |||
31 | This License is also included in this distribution in the file called | ||
32 | "MIT-COPYING". | ||
33 | |||
34 | EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS | ||
35 | PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | ||
36 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
37 | PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR | ||
38 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
39 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
40 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
41 | */ /**************************************************************************/ | ||
42 | |||
43 | #include "services_headers.h" | ||
44 | #include "buffer_manager.h" | ||
45 | #include "kernelbuffer.h" | ||
46 | #include "kerneldisplay.h" | ||
47 | #include "pvr_bridge_km.h" | ||
48 | #include "pdump_km.h" | ||
49 | #include "deviceid.h" | ||
50 | |||
51 | #include "lists.h" | ||
52 | #if defined(CONFIG_GCBV) | ||
53 | #include "gc_bvmapping.h" | ||
54 | #endif | ||
55 | |||
56 | PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID); | ||
57 | PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID); | ||
58 | |||
59 | #if defined(SUPPORT_MISR_IN_THREAD) | ||
60 | void OSVSyncMISR(IMG_HANDLE, IMG_BOOL); | ||
61 | #endif | ||
62 | |||
63 | #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) | ||
64 | IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie, | ||
65 | IMG_BOOL bScheduleMISR); | ||
66 | #endif | ||
67 | /*********************************************************************** | ||
68 | Local Display Class Structures | ||
69 | ************************************************************************/ | ||
70 | typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE; | ||
71 | |||
72 | /* | ||
73 | Display Class Buffer Info | ||
74 | */ | ||
75 | typedef struct PVRSRV_DC_BUFFER_TAG | ||
76 | { | ||
77 | /* BC/DC common details - THIS MUST BE THE FIRST MEMBER */ | ||
78 | PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer; | ||
79 | |||
80 | struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo; | ||
81 | struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain; | ||
82 | } PVRSRV_DC_BUFFER; | ||
83 | |||
84 | /* | ||
85 | Display Device Class kernel swapchain information structure | ||
86 | */ | ||
87 | typedef struct PVRSRV_DC_SWAPCHAIN_TAG | ||
88 | { | ||
89 | IMG_HANDLE hExtSwapChain; | ||
90 | IMG_UINT32 ui32SwapChainID; | ||
91 | IMG_UINT32 ui32RefCount; | ||
92 | IMG_UINT32 ui32Flags; | ||
93 | PVRSRV_QUEUE_INFO *psQueue; | ||
94 | PVRSRV_DC_BUFFER asBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS]; | ||
95 | IMG_UINT32 ui32BufferCount; | ||
96 | PVRSRV_DC_BUFFER *psLastFlipBuffer; | ||
97 | IMG_UINT32 ui32MinSwapInterval; | ||
98 | IMG_UINT32 ui32MaxSwapInterval; | ||
99 | #if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) | ||
100 | PVRSRV_KERNEL_SYNC_INFO **ppsLastSyncInfos; | ||
101 | IMG_UINT32 ui32LastNumSyncInfos; | ||
102 | #endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */ | ||
103 | struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo; | ||
104 | struct PVRSRV_DC_SWAPCHAIN_TAG *psNext; | ||
105 | } PVRSRV_DC_SWAPCHAIN; | ||
106 | |||
107 | |||
108 | /* | ||
109 | Display Device Class kernel swapchain referecne structure | ||
110 | */ | ||
111 | typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG | ||
112 | { | ||
113 | struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain; | ||
114 | IMG_HANDLE hResItem; | ||
115 | } PVRSRV_DC_SWAPCHAIN_REF; | ||
116 | |||
117 | |||
118 | /* | ||
119 | Display Device Class kernel services information structure | ||
120 | */ | ||
121 | typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG | ||
122 | { | ||
123 | IMG_UINT32 ui32RefCount; | ||
124 | IMG_UINT32 ui32DeviceID; | ||
125 | IMG_HANDLE hExtDevice; | ||
126 | PPVRSRV_DC_SRV2DISP_KMJTABLE psFuncTable; | ||
127 | IMG_HANDLE hDevMemContext; | ||
128 | PVRSRV_DC_BUFFER sSystemBuffer; | ||
129 | struct PVRSRV_DC_SWAPCHAIN_TAG *psDCSwapChainShared; | ||
130 | } PVRSRV_DISPLAYCLASS_INFO; | ||
131 | |||
132 | |||
133 | /* | ||
134 | Per-context Display Device Class kernel services information structure | ||
135 | */ | ||
136 | typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG | ||
137 | { | ||
138 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
139 | PRESMAN_ITEM hResItem; | ||
140 | } PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO; | ||
141 | |||
142 | |||
143 | /*********************************************************************** | ||
144 | Local Buffer Class Structures | ||
145 | ************************************************************************/ | ||
146 | typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE; | ||
147 | |||
148 | /* | ||
149 | Buffer Class Buffer Info | ||
150 | */ | ||
151 | typedef struct PVRSRV_BC_BUFFER_TAG | ||
152 | { | ||
153 | /* BC/DC common details - THIS MUST BE THE FIRST MEMBER */ | ||
154 | PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer; | ||
155 | |||
156 | struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo; | ||
157 | } PVRSRV_BC_BUFFER; | ||
158 | |||
159 | |||
160 | /* | ||
161 | Buffer Device Class kernel services information structure | ||
162 | */ | ||
163 | typedef struct PVRSRV_BUFFERCLASS_INFO_TAG | ||
164 | { | ||
165 | IMG_UINT32 ui32RefCount; | ||
166 | IMG_UINT32 ui32DeviceID; | ||
167 | IMG_HANDLE hExtDevice; | ||
168 | PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable; | ||
169 | IMG_HANDLE hDevMemContext; | ||
170 | /* buffer info returned from 3rd party driver */ | ||
171 | IMG_UINT32 ui32BufferCount; | ||
172 | PVRSRV_BC_BUFFER *psBuffer; | ||
173 | |||
174 | } PVRSRV_BUFFERCLASS_INFO; | ||
175 | |||
176 | |||
177 | /* | ||
178 | Per-context Buffer Device Class kernel services information structure | ||
179 | */ | ||
180 | typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG | ||
181 | { | ||
182 | PVRSRV_BUFFERCLASS_INFO *psBCInfo; | ||
183 | IMG_HANDLE hResItem; | ||
184 | } PVRSRV_BUFFERCLASS_PERCONTEXT_INFO; | ||
185 | |||
186 | |||
187 | /*! | ||
188 | ****************************************************************************** | ||
189 | @Function DCDeviceHandleToDCInfo | ||
190 | |||
191 | @Description | ||
192 | |||
193 | Convert a client-visible 3rd party device class handle to an internal | ||
194 | PVRSRV_DISPLAYCLASS_INFO pointer. | ||
195 | |||
196 | @Input hDeviceKM - handle to display class device, returned from OpenDCDevice | ||
197 | |||
198 | @Return | ||
199 | success: pointer to PVRSRV_DISPLAYCLASS_INFO | ||
200 | failure: IMG_NULL | ||
201 | ******************************************************************************/ | ||
202 | static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM) | ||
203 | { | ||
204 | PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; | ||
205 | |||
206 | psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM; | ||
207 | |||
208 | return psDCPerContextInfo->psDCInfo; | ||
209 | } | ||
210 | |||
211 | |||
212 | /*! | ||
213 | ****************************************************************************** | ||
214 | @Function BCDeviceHandleToBCInfo | ||
215 | |||
216 | @Description | ||
217 | |||
218 | Convert a client-visible 3rd party buffer class handle to an internal | ||
219 | PVRSRV_BUFFERCLASS_INFO pointer. | ||
220 | |||
221 | @Input hDeviceKM - handle to buffer class device, returned from OpenBCDevice | ||
222 | |||
223 | @Return | ||
224 | success: pointer to PVRSRV_BUFFERCLASS_INFO | ||
225 | failure: IMG_NULL | ||
226 | ******************************************************************************/ | ||
227 | static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM) | ||
228 | { | ||
229 | PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; | ||
230 | |||
231 | psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM; | ||
232 | |||
233 | return psBCPerContextInfo->psBCInfo; | ||
234 | } | ||
235 | |||
236 | /*! | ||
237 | ****************************************************************************** | ||
238 | @Function PVRSRVEnumerateDCKM_ForEachVaCb | ||
239 | |||
240 | @Description | ||
241 | |||
242 | Enumerates the device node (if is of the same class as given). | ||
243 | |||
244 | @Input psDeviceNode - The device node to be enumerated | ||
245 | va - variable arguments list, with: | ||
246 | pui32DevCount - The device count pointer (to be increased) | ||
247 | ppui32DevID - The pointer to the device IDs pointer (to be updated and increased) | ||
248 | peDeviceClass - The pointer to the device class of the psDeviceNode's to be enumerated. | ||
249 | ******************************************************************************/ | ||
250 | static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) | ||
251 | { | ||
252 | IMG_UINT *pui32DevCount; | ||
253 | IMG_UINT32 **ppui32DevID; | ||
254 | PVRSRV_DEVICE_CLASS peDeviceClass; | ||
255 | |||
256 | pui32DevCount = va_arg(va, IMG_UINT*); | ||
257 | ppui32DevID = va_arg(va, IMG_UINT32**); | ||
258 | peDeviceClass = va_arg(va, PVRSRV_DEVICE_CLASS); | ||
259 | |||
260 | if ((psDeviceNode->sDevId.eDeviceClass == peDeviceClass) | ||
261 | && (psDeviceNode->sDevId.eDeviceType == PVRSRV_DEVICE_TYPE_EXT)) | ||
262 | { | ||
263 | (*pui32DevCount)++; | ||
264 | if(*ppui32DevID) | ||
265 | { | ||
266 | *(*ppui32DevID)++ = psDeviceNode->sDevId.ui32DeviceIndex; | ||
267 | } | ||
268 | } | ||
269 | } | ||
270 | |||
271 | |||
272 | /*! | ||
273 | ****************************************************************************** | ||
274 | |||
275 | @Function PVRSRVEnumerateDCKM | ||
276 | |||
277 | @Description | ||
278 | |||
279 | Enumerates devices available in a given class. | ||
280 | On first call, pass valid ptr for pui32DevCount and IMG_NULL for pui32DevID, | ||
281 | On second call, pass same ptr for pui32DevCount and client allocated ptr | ||
282 | for pui32DevID device id list | ||
283 | |||
284 | @Input hServices - handle for services connection | ||
285 | @Input ui32DevClass - device class identifier | ||
286 | @Output pui32DevCount - number of devices available in class | ||
287 | @Output pui32DevID - list of device ids in the device class | ||
288 | |||
289 | @Return | ||
290 | success: handle to matching display class device | ||
291 | failure: IMG_NULL | ||
292 | |||
293 | ******************************************************************************/ | ||
294 | IMG_EXPORT | ||
295 | PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass, | ||
296 | IMG_UINT32 *pui32DevCount, | ||
297 | IMG_UINT32 *pui32DevID ) | ||
298 | { | ||
299 | /*PVRSRV_DEVICE_NODE *psDeviceNode;*/ | ||
300 | IMG_UINT ui32DevCount = 0; | ||
301 | SYS_DATA *psSysData; | ||
302 | |||
303 | SysAcquireData(&psSysData); | ||
304 | |||
305 | /* search devonode list for devices in specified class and return the device ids */ | ||
306 | List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList, | ||
307 | &PVRSRVEnumerateDCKM_ForEachVaCb, | ||
308 | &ui32DevCount, | ||
309 | &pui32DevID, | ||
310 | DeviceClass); | ||
311 | |||
312 | if(pui32DevCount) | ||
313 | { | ||
314 | *pui32DevCount = ui32DevCount; | ||
315 | } | ||
316 | else if(pui32DevID == IMG_NULL) | ||
317 | { | ||
318 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumerateDCKM: Invalid parameters")); | ||
319 | return (PVRSRV_ERROR_INVALID_PARAMS); | ||
320 | } | ||
321 | |||
322 | return PVRSRV_OK; | ||
323 | } | ||
324 | |||
325 | |||
326 | /*! | ||
327 | ****************************************************************************** | ||
328 | |||
329 | @Function PVRSRVRegisterDCDeviceKM | ||
330 | |||
331 | @Description | ||
332 | |||
333 | registers an external device with the system | ||
334 | |||
335 | @Input psFuncTable : device function table | ||
336 | |||
337 | @Output pui32DeviceID : unique device key (for case of multiple identical devices) | ||
338 | |||
339 | @Return PVRSRV_ERROR : | ||
340 | |||
341 | ******************************************************************************/ | ||
342 | static | ||
343 | PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable, | ||
344 | IMG_UINT32 *pui32DeviceID) | ||
345 | { | ||
346 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL; | ||
347 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
348 | SYS_DATA *psSysData; | ||
349 | |||
350 | /* | ||
351 | IN: | ||
352 | - name of client side ext. device driver library for subsequent loading | ||
353 | - predefined list of callbacks into kernel ext. device driver (based on class type) | ||
354 | |||
355 | FUNCTION TASKS: | ||
356 | - allocate display device class info structure | ||
357 | - hang ext.device kernel callbacks on this structure (pfnKSwapToSystem) | ||
358 | |||
359 | OUT: | ||
360 | - DEVICE_ID | ||
361 | - pass back devinfo? no | ||
362 | |||
363 | Q&A: | ||
364 | - DEVICE_ID passed in or allocated - assume allocate | ||
365 | */ | ||
366 | |||
367 | SysAcquireData(&psSysData); | ||
368 | |||
369 | /* | ||
370 | If we got this far we're doing dynamic enumeration | ||
371 | or first time static registration | ||
372 | */ | ||
373 | |||
374 | /* Allocate device control block */ | ||
375 | if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, | ||
376 | sizeof(*psDCInfo), | ||
377 | (IMG_VOID **)&psDCInfo, IMG_NULL, | ||
378 | "Display Class Info") != PVRSRV_OK) | ||
379 | { | ||
380 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDCInfo alloc")); | ||
381 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
382 | } | ||
383 | OSMemSet (psDCInfo, 0, sizeof(*psDCInfo)); | ||
384 | |||
385 | /* setup the display device information structure */ | ||
386 | if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, | ||
387 | sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), | ||
388 | (IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL, | ||
389 | "Function table for SRVKM->DISPLAY") != PVRSRV_OK) | ||
390 | { | ||
391 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psFuncTable alloc")); | ||
392 | goto ErrorExit; | ||
393 | } | ||
394 | OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE)); | ||
395 | |||
396 | /* copy the jump table */ | ||
397 | *psDCInfo->psFuncTable = *psFuncTable; | ||
398 | |||
399 | /* Allocate device node */ | ||
400 | if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
401 | sizeof(PVRSRV_DEVICE_NODE), | ||
402 | (IMG_VOID **)&psDeviceNode, IMG_NULL, | ||
403 | "Device Node") != PVRSRV_OK) | ||
404 | { | ||
405 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDCDeviceKM: Failed psDeviceNode alloc")); | ||
406 | goto ErrorExit; | ||
407 | } | ||
408 | OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE)); | ||
409 | |||
410 | psDeviceNode->pvDevice = (IMG_VOID*)psDCInfo; | ||
411 | psDeviceNode->ui32pvDeviceSize = sizeof(*psDCInfo); | ||
412 | psDeviceNode->ui32RefCount = 1; | ||
413 | psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT; | ||
414 | psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY; | ||
415 | psDeviceNode->psSysData = psSysData; | ||
416 | |||
417 | /* allocate a unique device id */ | ||
418 | if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK) | ||
419 | { | ||
420 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID")); | ||
421 | goto ErrorExit; | ||
422 | } | ||
423 | psDCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex; | ||
424 | if (pui32DeviceID) | ||
425 | { | ||
426 | *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex; | ||
427 | } | ||
428 | |||
429 | /* Register the device with the system */ | ||
430 | SysRegisterExternalDevice(psDeviceNode); | ||
431 | |||
432 | /* and finally insert the device into the dev-list */ | ||
433 | List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode); | ||
434 | |||
435 | return PVRSRV_OK; | ||
436 | |||
437 | ErrorExit: | ||
438 | |||
439 | if(psDCInfo->psFuncTable) | ||
440 | { | ||
441 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL); | ||
442 | psDCInfo->psFuncTable = IMG_NULL; | ||
443 | } | ||
444 | |||
445 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL); | ||
446 | /*not nulling pointer, out of scope*/ | ||
447 | |||
448 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
449 | } | ||
450 | |||
451 | /*! | ||
452 | ****************************************************************************** | ||
453 | |||
454 | @Function PVRSRVRemoveDCDeviceKM | ||
455 | |||
456 | @Description | ||
457 | |||
458 | Removes external device from services system record | ||
459 | |||
460 | @Input ui32DeviceIndex : unique device key (for case of multiple identical devices) | ||
461 | |||
462 | @Return PVRSRV_ERROR : | ||
463 | |||
464 | ******************************************************************************/ | ||
465 | static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex) | ||
466 | { | ||
467 | SYS_DATA *psSysData; | ||
468 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
469 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
470 | |||
471 | SysAcquireData(&psSysData); | ||
472 | |||
473 | /*search the node matching the devindex and display class*/ | ||
474 | psDeviceNode = (PVRSRV_DEVICE_NODE*) | ||
475 | List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, | ||
476 | &MatchDeviceKM_AnyVaCb, | ||
477 | ui32DevIndex, | ||
478 | IMG_FALSE, | ||
479 | PVRSRV_DEVICE_CLASS_DISPLAY); | ||
480 | if (!psDeviceNode) | ||
481 | { | ||
482 | /*device not found*/ | ||
483 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex)); | ||
484 | return PVRSRV_ERROR_NO_DEVICENODE_FOUND; | ||
485 | } | ||
486 | |||
487 | /* setup DCInfo ptr */ | ||
488 | psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice; | ||
489 | |||
490 | /* | ||
491 | The device can only be removed if there are | ||
492 | no open connections in the Services interface | ||
493 | */ | ||
494 | if(psDCInfo->ui32RefCount == 0) | ||
495 | { | ||
496 | /* | ||
497 | Remove from the device list. | ||
498 | */ | ||
499 | List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode); | ||
500 | |||
501 | /* Unregister the device with the system */ | ||
502 | SysRemoveExternalDevice(psDeviceNode); | ||
503 | |||
504 | /* | ||
505 | OK found a device with a matching devindex | ||
506 | remove registration information | ||
507 | */ | ||
508 | PVR_ASSERT(psDCInfo->ui32RefCount == 0); | ||
509 | (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex); | ||
510 | (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL); | ||
511 | psDCInfo->psFuncTable = IMG_NULL; | ||
512 | (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL); | ||
513 | /*not nulling original pointer, overwritten*/ | ||
514 | (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL); | ||
515 | /*not nulling pointer, out of scope*/ | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: failed as %d Services DC API connections are still open", psDCInfo->ui32RefCount)); | ||
520 | return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE; | ||
521 | } | ||
522 | |||
523 | return PVRSRV_OK; | ||
524 | } | ||
525 | |||
526 | |||
527 | /*! | ||
528 | ****************************************************************************** | ||
529 | |||
530 | @Function PVRSRVRegisterBCDeviceKM | ||
531 | |||
532 | @Description | ||
533 | |||
534 | registers an external device with the system | ||
535 | |||
536 | @Input psFuncTable : device function table | ||
537 | @Input ui32DeviceIndex : unique device key (for case of multiple identical devices) | ||
538 | |||
539 | @Return PVRSRV_ERROR : | ||
540 | |||
541 | ******************************************************************************/ | ||
542 | static | ||
543 | PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable, | ||
544 | IMG_UINT32 *pui32DeviceID) | ||
545 | { | ||
546 | PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL; | ||
547 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
548 | SYS_DATA *psSysData; | ||
549 | /* | ||
550 | IN: | ||
551 | - name of client side ext. device driver library for subsequent loading | ||
552 | - predefined list of callbacks into kernel ext. device driver (based on class type) | ||
553 | |||
554 | FUNCTION TASKS: | ||
555 | - allocate buffer device class info structure | ||
556 | |||
557 | OUT: | ||
558 | - DEVICE_ID | ||
559 | - pass back devinfo? no | ||
560 | |||
561 | Q&A: | ||
562 | - DEVICE_ID passed in or allocated - assume allcoate | ||
563 | */ | ||
564 | |||
565 | SysAcquireData(&psSysData); | ||
566 | |||
567 | /* | ||
568 | If we got this far we're doing dynamic enumeration | ||
569 | or first time static registration | ||
570 | */ | ||
571 | |||
572 | /* Allocate device control block */ | ||
573 | if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, | ||
574 | sizeof(*psBCInfo), | ||
575 | (IMG_VOID **)&psBCInfo, IMG_NULL, | ||
576 | "Buffer Class Info") != PVRSRV_OK) | ||
577 | { | ||
578 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psBCInfo alloc")); | ||
579 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
580 | } | ||
581 | OSMemSet (psBCInfo, 0, sizeof(*psBCInfo)); | ||
582 | |||
583 | /* setup the buffer device information structure */ | ||
584 | if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, | ||
585 | sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), | ||
586 | (IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL, | ||
587 | "Function table for SRVKM->BUFFER") != PVRSRV_OK) | ||
588 | { | ||
589 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psFuncTable alloc")); | ||
590 | goto ErrorExit; | ||
591 | } | ||
592 | OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE)); | ||
593 | |||
594 | /* copy the jump table */ | ||
595 | *psBCInfo->psFuncTable = *psFuncTable; | ||
596 | |||
597 | /* Allocate device node */ | ||
598 | if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP, | ||
599 | sizeof(PVRSRV_DEVICE_NODE), | ||
600 | (IMG_VOID **)&psDeviceNode, IMG_NULL, | ||
601 | "Device Node") != PVRSRV_OK) | ||
602 | { | ||
603 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed psDeviceNode alloc")); | ||
604 | goto ErrorExit; | ||
605 | } | ||
606 | OSMemSet (psDeviceNode, 0, sizeof(PVRSRV_DEVICE_NODE)); | ||
607 | |||
608 | psDeviceNode->pvDevice = (IMG_VOID*)psBCInfo; | ||
609 | psDeviceNode->ui32pvDeviceSize = sizeof(*psBCInfo); | ||
610 | psDeviceNode->ui32RefCount = 1; | ||
611 | psDeviceNode->sDevId.eDeviceType = PVRSRV_DEVICE_TYPE_EXT; | ||
612 | psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER; | ||
613 | psDeviceNode->psSysData = psSysData; | ||
614 | |||
615 | /* allocate a unique device id */ | ||
616 | if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK) | ||
617 | { | ||
618 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID")); | ||
619 | goto ErrorExit; | ||
620 | } | ||
621 | psBCInfo->ui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex; | ||
622 | if (pui32DeviceID) | ||
623 | { | ||
624 | *pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex; | ||
625 | } | ||
626 | |||
627 | /* and finally insert the device into the dev-list */ | ||
628 | List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode); | ||
629 | |||
630 | return PVRSRV_OK; | ||
631 | |||
632 | ErrorExit: | ||
633 | |||
634 | if(psBCInfo->psFuncTable) | ||
635 | { | ||
636 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PPVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL); | ||
637 | psBCInfo->psFuncTable = IMG_NULL; | ||
638 | } | ||
639 | |||
640 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL); | ||
641 | /*not nulling shared pointer, wasn't allocated to this point*/ | ||
642 | |||
643 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
644 | } | ||
645 | |||
646 | |||
647 | /*! | ||
648 | ****************************************************************************** | ||
649 | |||
650 | @Function PVRSRVRemoveBCDeviceKM | ||
651 | |||
652 | @Description | ||
653 | |||
654 | Removes external device from services system record | ||
655 | |||
656 | @Input ui32DeviceIndex : unique device key (for case of multiple identical devices) | ||
657 | |||
658 | @Return PVRSRV_ERROR : | ||
659 | |||
660 | ******************************************************************************/ | ||
661 | static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex) | ||
662 | { | ||
663 | SYS_DATA *psSysData; | ||
664 | PVRSRV_DEVICE_NODE *psDevNode; | ||
665 | PVRSRV_BUFFERCLASS_INFO *psBCInfo; | ||
666 | |||
667 | SysAcquireData(&psSysData); | ||
668 | |||
669 | /*search the device node with the devindex and buffer class*/ | ||
670 | psDevNode = (PVRSRV_DEVICE_NODE*) | ||
671 | List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, | ||
672 | &MatchDeviceKM_AnyVaCb, | ||
673 | ui32DevIndex, | ||
674 | IMG_FALSE, | ||
675 | PVRSRV_DEVICE_CLASS_BUFFER); | ||
676 | |||
677 | if (!psDevNode) | ||
678 | { | ||
679 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: requested device %d not present", ui32DevIndex)); | ||
680 | return PVRSRV_ERROR_NO_DEVICENODE_FOUND; | ||
681 | } | ||
682 | |||
683 | /* set-up devnode ptr */ | ||
684 | /* psDevNode = *(ppsDevNode); */ | ||
685 | /* setup BCInfo ptr */ | ||
686 | psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice; | ||
687 | |||
688 | /* | ||
689 | The device can only be removed if there are | ||
690 | no open connections in the Services interface | ||
691 | */ | ||
692 | if(psBCInfo->ui32RefCount == 0) | ||
693 | { | ||
694 | /* | ||
695 | Remove from the device list. | ||
696 | */ | ||
697 | List_PVRSRV_DEVICE_NODE_Remove(psDevNode); | ||
698 | |||
699 | /* | ||
700 | OK found a device with a matching devindex | ||
701 | remove registration information | ||
702 | */ | ||
703 | (IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex); | ||
704 | (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL); | ||
705 | psBCInfo->psFuncTable = IMG_NULL; | ||
706 | (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL); | ||
707 | /*not nulling pointer, copy on stack*/ | ||
708 | (IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL); | ||
709 | /*not nulling pointer, out of scope*/ | ||
710 | } | ||
711 | else | ||
712 | { | ||
713 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveBCDeviceKM: failed as %d Services BC API connections are still open", psBCInfo->ui32RefCount)); | ||
714 | return PVRSRV_ERROR_UNABLE_TO_REMOVE_DEVICE; | ||
715 | } | ||
716 | |||
717 | return PVRSRV_OK; | ||
718 | } | ||
719 | |||
720 | |||
721 | |||
722 | /*! | ||
723 | ****************************************************************************** | ||
724 | |||
725 | @Function PVRSRVCloseDCDeviceKM | ||
726 | |||
727 | @Description | ||
728 | |||
729 | Closes a connection to the Display Class device | ||
730 | |||
731 | @Input hDeviceKM : device handle | ||
732 | |||
733 | @Return PVRSRV_ERROR : | ||
734 | |||
735 | ******************************************************************************/ | ||
736 | IMG_EXPORT | ||
737 | PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM) | ||
738 | { | ||
739 | PVRSRV_ERROR eError; | ||
740 | PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; | ||
741 | |||
742 | psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM; | ||
743 | |||
744 | /* Remove the item from the resman list and trigger the callback. */ | ||
745 | eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem, CLEANUP_WITH_POLL); | ||
746 | |||
747 | return eError; | ||
748 | } | ||
749 | |||
750 | |||
751 | static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam, | ||
752 | IMG_UINT32 ui32Param, | ||
753 | IMG_BOOL bDummy) | ||
754 | { | ||
755 | PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; | ||
756 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
757 | |||
758 | PVR_UNREFERENCED_PARAMETER(ui32Param); | ||
759 | PVR_UNREFERENCED_PARAMETER(bDummy); | ||
760 | |||
761 | psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)pvParam; | ||
762 | psDCInfo = psDCPerContextInfo->psDCInfo; | ||
763 | |||
764 | if(psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount != 0) | ||
765 | { | ||
766 | PVR_DPF((PVR_DBG_MESSAGE,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)", | ||
767 | &psDCInfo->sSystemBuffer.sDeviceClassBuffer, | ||
768 | psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount)); | ||
769 | } | ||
770 | |||
771 | psDCInfo->ui32RefCount--; | ||
772 | if(psDCInfo->ui32RefCount == 0) | ||
773 | { | ||
774 | /* close the external device */ | ||
775 | psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice); | ||
776 | |||
777 | PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); | ||
778 | |||
779 | psDCInfo->hDevMemContext = IMG_NULL; | ||
780 | psDCInfo->hExtDevice = IMG_NULL; | ||
781 | } | ||
782 | |||
783 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL); | ||
784 | /*not nulling pointer, copy on stack*/ | ||
785 | |||
786 | return PVRSRV_OK; | ||
787 | } | ||
788 | |||
789 | |||
790 | /*! | ||
791 | ****************************************************************************** | ||
792 | |||
793 | @Function PVRSRVOpenDCDeviceKM | ||
794 | |||
795 | @Description | ||
796 | |||
797 | Opens a connection to the Display Class device, associating the connection | ||
798 | with a Device Memory Context for a services managed device | ||
799 | |||
800 | @Input psPerProc : Per-process data | ||
801 | @Input ui32DeviceID : unique device index | ||
802 | @Input hDevCookie : devcookie used to derive the Device Memory | ||
803 | Context into BC surfaces will be mapped into | ||
804 | @Outut phDeviceKM : handle to the DC device | ||
805 | |||
806 | @Return PVRSRV_ERROR : | ||
807 | |||
808 | ******************************************************************************/ | ||
809 | IMG_EXPORT | ||
810 | PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, | ||
811 | IMG_UINT32 ui32DeviceID, | ||
812 | IMG_HANDLE hDevCookie, | ||
813 | IMG_HANDLE *phDeviceKM) | ||
814 | { | ||
815 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
816 | PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo; | ||
817 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
818 | SYS_DATA *psSysData; | ||
819 | PVRSRV_ERROR eError; | ||
820 | |||
821 | if(!phDeviceKM || !hDevCookie) | ||
822 | { | ||
823 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Invalid params")); | ||
824 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
825 | } | ||
826 | |||
827 | SysAcquireData(&psSysData); | ||
828 | |||
829 | /* find the matching devicenode */ | ||
830 | psDeviceNode = (PVRSRV_DEVICE_NODE*) | ||
831 | List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, | ||
832 | &MatchDeviceKM_AnyVaCb, | ||
833 | ui32DeviceID, | ||
834 | IMG_FALSE, | ||
835 | PVRSRV_DEVICE_CLASS_DISPLAY); | ||
836 | if (!psDeviceNode) | ||
837 | { | ||
838 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: no devnode matching index %d", ui32DeviceID)); | ||
839 | return PVRSRV_ERROR_NO_DEVICENODE_FOUND; | ||
840 | } | ||
841 | psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice; | ||
842 | |||
843 | /* | ||
844 | Allocate the per-context DC Info before calling the external device, | ||
845 | to make error handling easier. | ||
846 | */ | ||
847 | if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
848 | sizeof(*psDCPerContextInfo), | ||
849 | (IMG_VOID **)&psDCPerContextInfo, IMG_NULL, | ||
850 | "Display Class per Context Info") != PVRSRV_OK) | ||
851 | { | ||
852 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed psDCPerContextInfo alloc")); | ||
853 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
854 | } | ||
855 | OSMemSet(psDCPerContextInfo, 0, sizeof(*psDCPerContextInfo)); | ||
856 | |||
857 | if(psDCInfo->ui32RefCount++ == 0) | ||
858 | { | ||
859 | |||
860 | psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; | ||
861 | |||
862 | /* store the device kernel context to map into */ | ||
863 | psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext; | ||
864 | |||
865 | /* create a syncinfo for the device's system surface */ | ||
866 | eError = PVRSRVAllocSyncInfoKM(IMG_NULL, | ||
867 | (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext, | ||
868 | &psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo); | ||
869 | if(eError != PVRSRV_OK) | ||
870 | { | ||
871 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed sync info alloc")); | ||
872 | psDCInfo->ui32RefCount--; | ||
873 | return eError; | ||
874 | } | ||
875 | |||
876 | /* open the external device */ | ||
877 | eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID, | ||
878 | &psDCInfo->hExtDevice, | ||
879 | (PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM); | ||
880 | if(eError != PVRSRV_OK) | ||
881 | { | ||
882 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device")); | ||
883 | psDCInfo->ui32RefCount--; | ||
884 | PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); | ||
885 | return eError; | ||
886 | } | ||
887 | |||
888 | psDCPerContextInfo->psDCInfo = psDCInfo; | ||
889 | eError = PVRSRVGetDCSystemBufferKM(psDCPerContextInfo, IMG_NULL); | ||
890 | if(eError != PVRSRV_OK) | ||
891 | { | ||
892 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to get system buffer")); | ||
893 | psDCInfo->ui32RefCount--; | ||
894 | PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); | ||
895 | return eError; | ||
896 | } | ||
897 | psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount = 0; | ||
898 | } | ||
899 | else | ||
900 | { | ||
901 | psDCPerContextInfo->psDCInfo = psDCInfo; | ||
902 | } | ||
903 | |||
904 | psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, | ||
905 | RESMAN_TYPE_DISPLAYCLASS_DEVICE, | ||
906 | psDCPerContextInfo, | ||
907 | 0, | ||
908 | &CloseDCDeviceCallBack); | ||
909 | |||
910 | /* return a reference to the DCPerContextInfo */ | ||
911 | *phDeviceKM = (IMG_HANDLE)psDCPerContextInfo; | ||
912 | |||
913 | return PVRSRV_OK; | ||
914 | } | ||
915 | |||
916 | |||
917 | /*! | ||
918 | ****************************************************************************** | ||
919 | |||
920 | @Function PVRSRVEnumDCFormatsKM | ||
921 | |||
922 | @Description | ||
923 | |||
924 | Enumerates the devices pixel formats | ||
925 | |||
926 | @Input hDeviceKM : device handle | ||
927 | @Output pui32Count : number of pixel formats | ||
928 | @Output psFormat : format list | ||
929 | |||
930 | @Return PVRSRV_ERROR : | ||
931 | |||
932 | ******************************************************************************/ | ||
933 | IMG_EXPORT | ||
934 | PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM, | ||
935 | IMG_UINT32 *pui32Count, | ||
936 | DISPLAY_FORMAT *psFormat) | ||
937 | { | ||
938 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
939 | |||
940 | if(!hDeviceKM || !pui32Count || !psFormat) | ||
941 | { | ||
942 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCFormatsKM: Invalid parameters")); | ||
943 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
944 | } | ||
945 | |||
946 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
947 | |||
948 | /* call into the display device driver to get info */ | ||
949 | return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat); | ||
950 | } | ||
951 | |||
952 | |||
953 | |||
954 | /*! | ||
955 | ****************************************************************************** | ||
956 | |||
957 | @Function PVRSRVEnumDCDimsKM | ||
958 | |||
959 | @Description | ||
960 | |||
961 | Enumerates the devices mode dimensions for a given pixel format | ||
962 | |||
963 | @Input hDeviceKM : device handle | ||
964 | @Input psFormat : pixel format | ||
965 | @Output pui32Count : number of dimensions | ||
966 | @Output psDim : dimensions list | ||
967 | |||
968 | @Return PVRSRV_ERROR : | ||
969 | |||
970 | ******************************************************************************/ | ||
971 | IMG_EXPORT | ||
972 | PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM, | ||
973 | DISPLAY_FORMAT *psFormat, | ||
974 | IMG_UINT32 *pui32Count, | ||
975 | DISPLAY_DIMS *psDim) | ||
976 | { | ||
977 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
978 | |||
979 | if(!hDeviceKM || !pui32Count || !psFormat) // psDim==NULL to query number of dims | ||
980 | { | ||
981 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters")); | ||
982 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
983 | } | ||
984 | |||
985 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
986 | |||
987 | /* call into the display device driver to get info */ | ||
988 | return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim); | ||
989 | } | ||
990 | |||
991 | |||
992 | /*! | ||
993 | ****************************************************************************** | ||
994 | |||
995 | @Function PVRSRVGetDCSystemBufferKM | ||
996 | |||
997 | @Description | ||
998 | |||
999 | Get the primary surface and optionally return its buffer handle | ||
1000 | |||
1001 | @Input hDeviceKM : device handle | ||
1002 | @Output phBuffer : Optional buffer handle | ||
1003 | |||
1004 | @Return PVRSRV_ERROR : | ||
1005 | |||
1006 | ******************************************************************************/ | ||
1007 | IMG_EXPORT | ||
1008 | PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM, | ||
1009 | IMG_HANDLE *phBuffer) | ||
1010 | { | ||
1011 | PVRSRV_ERROR eError; | ||
1012 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1013 | IMG_HANDLE hExtBuffer; | ||
1014 | |||
1015 | if(!hDeviceKM) | ||
1016 | { | ||
1017 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters")); | ||
1018 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1019 | } | ||
1020 | |||
1021 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1022 | |||
1023 | /* call into the display device driver to get info */ | ||
1024 | eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer); | ||
1025 | if(eError != PVRSRV_OK) | ||
1026 | { | ||
1027 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Failed to get valid buffer handle from external driver")); | ||
1028 | return eError; | ||
1029 | } | ||
1030 | |||
1031 | /* save the new info */ | ||
1032 | psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr; | ||
1033 | psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext; | ||
1034 | psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice; | ||
1035 | psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer = hExtBuffer; | ||
1036 | |||
1037 | psDCInfo->sSystemBuffer.psDCInfo = psDCInfo; | ||
1038 | |||
1039 | /* return handle */ | ||
1040 | if (phBuffer) | ||
1041 | { | ||
1042 | *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer); | ||
1043 | } | ||
1044 | |||
1045 | return PVRSRV_OK; | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | /****************************************************************************** | ||
1050 | |||
1051 | @Function PVRSRVGetDCInfoKM | ||
1052 | |||
1053 | @Description | ||
1054 | |||
1055 | Gets Display Class device Info | ||
1056 | |||
1057 | @Input hDeviceKM : device handle | ||
1058 | @Output psDisplayInfo | ||
1059 | |||
1060 | @Return PVRSRV_ERROR : | ||
1061 | |||
1062 | ******************************************************************************/ | ||
1063 | IMG_EXPORT | ||
1064 | PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM, | ||
1065 | DISPLAY_INFO *psDisplayInfo) | ||
1066 | { | ||
1067 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1068 | PVRSRV_ERROR eError; | ||
1069 | |||
1070 | if(!hDeviceKM || !psDisplayInfo) | ||
1071 | { | ||
1072 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCInfoKM: Invalid parameters")); | ||
1073 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1074 | } | ||
1075 | |||
1076 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1077 | |||
1078 | /* call into the display device driver to get info */ | ||
1079 | eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo); | ||
1080 | if (eError != PVRSRV_OK) | ||
1081 | { | ||
1082 | return eError; | ||
1083 | } | ||
1084 | |||
1085 | if (psDisplayInfo->ui32MaxSwapChainBuffers > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) | ||
1086 | { | ||
1087 | psDisplayInfo->ui32MaxSwapChainBuffers = PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS; | ||
1088 | } | ||
1089 | |||
1090 | return PVRSRV_OK; | ||
1091 | } | ||
1092 | |||
1093 | |||
1094 | IMG_EXPORT | ||
1095 | PVRSRV_ERROR PVRSRVDestroyDCSwapChainKM(IMG_HANDLE hSwapChainRef) | ||
1096 | { | ||
1097 | PVRSRV_ERROR eError; | ||
1098 | PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef; | ||
1099 | |||
1100 | if(!hSwapChainRef) | ||
1101 | { | ||
1102 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyDCSwapChainKM: Invalid parameters")); | ||
1103 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1104 | } | ||
1105 | |||
1106 | psSwapChainRef = hSwapChainRef; | ||
1107 | |||
1108 | eError = ResManFreeResByPtr(psSwapChainRef->hResItem, CLEANUP_WITH_POLL); | ||
1109 | |||
1110 | return eError; | ||
1111 | } | ||
1112 | |||
1113 | |||
1114 | static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain) | ||
1115 | { | ||
1116 | PVRSRV_ERROR eError; | ||
1117 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo; | ||
1118 | IMG_UINT32 i; | ||
1119 | |||
1120 | /* Update shared swapchains list */ | ||
1121 | if( psDCInfo->psDCSwapChainShared ) | ||
1122 | { | ||
1123 | if( psDCInfo->psDCSwapChainShared == psSwapChain ) | ||
1124 | { | ||
1125 | psDCInfo->psDCSwapChainShared = psSwapChain->psNext; | ||
1126 | } | ||
1127 | else | ||
1128 | { | ||
1129 | PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain; | ||
1130 | psCurrentSwapChain = psDCInfo->psDCSwapChainShared; | ||
1131 | while( psCurrentSwapChain->psNext ) | ||
1132 | { | ||
1133 | if( psCurrentSwapChain->psNext != psSwapChain ) | ||
1134 | { | ||
1135 | psCurrentSwapChain = psCurrentSwapChain->psNext; | ||
1136 | continue; | ||
1137 | } | ||
1138 | psCurrentSwapChain->psNext = psSwapChain->psNext; | ||
1139 | break; | ||
1140 | } | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | /* Destroy command queue before swapchain - it may use the swapchain when commands are flushed. */ | ||
1145 | PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue); | ||
1146 | |||
1147 | /* call into the display device driver to destroy a swapchain */ | ||
1148 | eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice, | ||
1149 | psSwapChain->hExtSwapChain); | ||
1150 | |||
1151 | if (eError != PVRSRV_OK) | ||
1152 | { | ||
1153 | PVR_DPF((PVR_DBG_ERROR,"DestroyDCSwapChainCallBack: Failed to destroy DC swap chain")); | ||
1154 | return eError; | ||
1155 | } | ||
1156 | |||
1157 | /* free the resources */ | ||
1158 | for(i=0; i<psSwapChain->ui32BufferCount; i++) | ||
1159 | { | ||
1160 | if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) | ||
1161 | { | ||
1162 | PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); | ||
1163 | } | ||
1164 | } | ||
1165 | |||
1166 | #if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) | ||
1167 | if (psSwapChain->ppsLastSyncInfos) | ||
1168 | { | ||
1169 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos, | ||
1170 | psSwapChain->ppsLastSyncInfos, IMG_NULL); | ||
1171 | } | ||
1172 | #endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */ | ||
1173 | |||
1174 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL); | ||
1175 | /*not nulling pointer, copy on stack*/ | ||
1176 | |||
1177 | return eError; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam, | ||
1182 | IMG_UINT32 ui32Param, | ||
1183 | IMG_BOOL bDummy) | ||
1184 | { | ||
1185 | PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF *) pvParam; | ||
1186 | PVRSRV_ERROR eError = PVRSRV_OK; | ||
1187 | IMG_UINT32 i; | ||
1188 | |||
1189 | PVR_UNREFERENCED_PARAMETER(ui32Param); | ||
1190 | PVR_UNREFERENCED_PARAMETER(bDummy); | ||
1191 | |||
1192 | for (i = 0; i < psSwapChainRef->psSwapChain->ui32BufferCount; i++) | ||
1193 | { | ||
1194 | if (psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0) | ||
1195 | { | ||
1196 | PVR_DPF((PVR_DBG_ERROR, "DestroyDCSwapChainRefCallBack: swapchain (0x%p) still mapped (ui32MemMapRefCount = %d)", | ||
1197 | &psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer, | ||
1198 | psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount)); | ||
1199 | } | ||
1200 | } | ||
1201 | |||
1202 | if(--psSwapChainRef->psSwapChain->ui32RefCount == 0) | ||
1203 | { | ||
1204 | eError = DestroyDCSwapChain(psSwapChainRef->psSwapChain); | ||
1205 | } | ||
1206 | |||
1207 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN_REF), psSwapChainRef, IMG_NULL); | ||
1208 | return eError; | ||
1209 | } | ||
1210 | |||
1211 | static PVRSRV_DC_SWAPCHAIN* PVRSRVFindSharedDCSwapChainKM(PVRSRV_DISPLAYCLASS_INFO *psDCInfo, | ||
1212 | IMG_UINT32 ui32SwapChainID) | ||
1213 | { | ||
1214 | PVRSRV_DC_SWAPCHAIN *psCurrentSwapChain; | ||
1215 | |||
1216 | for(psCurrentSwapChain = psDCInfo->psDCSwapChainShared; | ||
1217 | psCurrentSwapChain; | ||
1218 | psCurrentSwapChain = psCurrentSwapChain->psNext) | ||
1219 | { | ||
1220 | if(psCurrentSwapChain->ui32SwapChainID == ui32SwapChainID) | ||
1221 | return psCurrentSwapChain; | ||
1222 | } | ||
1223 | return IMG_NULL; | ||
1224 | } | ||
1225 | |||
1226 | static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *psPerProc, | ||
1227 | PVRSRV_DC_SWAPCHAIN *psSwapChain, | ||
1228 | PVRSRV_DC_SWAPCHAIN_REF **ppsSwapChainRef) | ||
1229 | { | ||
1230 | PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL; | ||
1231 | |||
1232 | /* Allocate swapchain reference structre*/ | ||
1233 | if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, | ||
1234 | sizeof(PVRSRV_DC_SWAPCHAIN_REF), | ||
1235 | (IMG_VOID **)&psSwapChainRef, IMG_NULL, | ||
1236 | "Display Class Swapchain Reference") != PVRSRV_OK) | ||
1237 | { | ||
1238 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainRefKM: Failed psSwapChainRef alloc")); | ||
1239 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
1240 | } | ||
1241 | OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF)); | ||
1242 | |||
1243 | /* Bump refcount */ | ||
1244 | psSwapChain->ui32RefCount++; | ||
1245 | |||
1246 | /* Create reference resource */ | ||
1247 | psSwapChainRef->psSwapChain = psSwapChain; | ||
1248 | psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext, | ||
1249 | RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, | ||
1250 | psSwapChainRef, | ||
1251 | 0, | ||
1252 | &DestroyDCSwapChainRefCallBack); | ||
1253 | *ppsSwapChainRef = psSwapChainRef; | ||
1254 | |||
1255 | return PVRSRV_OK; | ||
1256 | } | ||
1257 | |||
1258 | |||
1259 | IMG_EXPORT | ||
1260 | PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc, | ||
1261 | IMG_HANDLE hDeviceKM, | ||
1262 | IMG_UINT32 ui32Flags, | ||
1263 | DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib, | ||
1264 | DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib, | ||
1265 | IMG_UINT32 ui32BufferCount, | ||
1266 | IMG_UINT32 ui32OEMFlags, | ||
1267 | IMG_HANDLE *phSwapChainRef, | ||
1268 | IMG_UINT32 *pui32SwapChainID) | ||
1269 | { | ||
1270 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1271 | PVRSRV_DC_SWAPCHAIN *psSwapChain = IMG_NULL; | ||
1272 | PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL; | ||
1273 | PVRSRV_SYNC_DATA *apsSyncData[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS]; | ||
1274 | PVRSRV_QUEUE_INFO *psQueue = IMG_NULL; | ||
1275 | PVRSRV_ERROR eError; | ||
1276 | IMG_UINT32 i; | ||
1277 | DISPLAY_INFO sDisplayInfo; | ||
1278 | |||
1279 | |||
1280 | if(!hDeviceKM | ||
1281 | || !psDstSurfAttrib | ||
1282 | || !psSrcSurfAttrib | ||
1283 | || !phSwapChainRef | ||
1284 | || !pui32SwapChainID) | ||
1285 | { | ||
1286 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Invalid parameters")); | ||
1287 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1288 | } | ||
1289 | |||
1290 | if (ui32BufferCount > PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS) | ||
1291 | { | ||
1292 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too many buffers")); | ||
1293 | return PVRSRV_ERROR_TOOMANYBUFFERS; | ||
1294 | } | ||
1295 | |||
1296 | if (ui32BufferCount < 2) | ||
1297 | { | ||
1298 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Too few buffers")); | ||
1299 | return PVRSRV_ERROR_TOO_FEW_BUFFERS; | ||
1300 | } | ||
1301 | |||
1302 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1303 | |||
1304 | if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY ) | ||
1305 | { | ||
1306 | /* Query - use pui32SwapChainID as input */ | ||
1307 | psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID ); | ||
1308 | if( psSwapChain ) | ||
1309 | { | ||
1310 | /* Create new reference */ | ||
1311 | eError = PVRSRVCreateDCSwapChainRefKM(psPerProc, | ||
1312 | psSwapChain, | ||
1313 | &psSwapChainRef); | ||
1314 | if( eError != PVRSRV_OK ) | ||
1315 | { | ||
1316 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference")); | ||
1317 | return eError; | ||
1318 | } | ||
1319 | |||
1320 | *phSwapChainRef = (IMG_HANDLE)psSwapChainRef; | ||
1321 | return PVRSRV_OK; | ||
1322 | } | ||
1323 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: No shared SwapChain found for query")); | ||
1324 | return PVRSRV_ERROR_FLIP_CHAIN_EXISTS; | ||
1325 | } | ||
1326 | |||
1327 | /* Allocate swapchain control structure for srvkm */ | ||
1328 | if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP, | ||
1329 | sizeof(PVRSRV_DC_SWAPCHAIN), | ||
1330 | (IMG_VOID **)&psSwapChain, IMG_NULL, | ||
1331 | "Display Class Swapchain") != PVRSRV_OK) | ||
1332 | { | ||
1333 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed psSwapChain alloc")); | ||
1334 | eError = PVRSRV_ERROR_OUT_OF_MEMORY; | ||
1335 | goto ErrorExit; | ||
1336 | } | ||
1337 | OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN)); | ||
1338 | |||
1339 | /* Create a command queue for the swapchain */ | ||
1340 | eError = PVRSRVCreateCommandQueueKM(1024, &psQueue); | ||
1341 | if(eError != PVRSRV_OK) | ||
1342 | { | ||
1343 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create CmdQueue")); | ||
1344 | goto ErrorExit; | ||
1345 | } | ||
1346 | |||
1347 | /* store the Queue */ | ||
1348 | psSwapChain->psQueue = psQueue; | ||
1349 | |||
1350 | /* Create a Sync Object for each surface in the swapchain */ | ||
1351 | for(i=0; i<ui32BufferCount; i++) | ||
1352 | { | ||
1353 | eError = PVRSRVAllocSyncInfoKM(IMG_NULL, | ||
1354 | psDCInfo->hDevMemContext, | ||
1355 | &psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); | ||
1356 | if(eError != PVRSRV_OK) | ||
1357 | { | ||
1358 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to alloc syninfo for psSwapChain")); | ||
1359 | goto ErrorExit; | ||
1360 | } | ||
1361 | |||
1362 | /* setup common device class info */ | ||
1363 | psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr; | ||
1364 | psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext; | ||
1365 | psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice; | ||
1366 | |||
1367 | /* save off useful ptrs */ | ||
1368 | psSwapChain->asBuffer[i].psDCInfo = psDCInfo; | ||
1369 | psSwapChain->asBuffer[i].psSwapChain = psSwapChain; | ||
1370 | |||
1371 | /* syncinfos must be passed as array of syncdata ptrs to the 3rd party driver */ | ||
1372 | apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM; | ||
1373 | } | ||
1374 | |||
1375 | psSwapChain->ui32BufferCount = ui32BufferCount; | ||
1376 | psSwapChain->psDCInfo = psDCInfo; | ||
1377 | |||
1378 | #if defined(PDUMP) | ||
1379 | PDUMPCOMMENT("Allocate DC swap chain (SwapChainID == %u, BufferCount == %u)", | ||
1380 | *pui32SwapChainID, | ||
1381 | ui32BufferCount); | ||
1382 | PDUMPCOMMENT(" Src surface dimensions == %u x %u", | ||
1383 | psSrcSurfAttrib->sDims.ui32Width, | ||
1384 | psSrcSurfAttrib->sDims.ui32Height); | ||
1385 | PDUMPCOMMENT(" Dst surface dimensions == %u x %u", | ||
1386 | psDstSurfAttrib->sDims.ui32Width, | ||
1387 | psDstSurfAttrib->sDims.ui32Height); | ||
1388 | #endif | ||
1389 | |||
1390 | eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, &sDisplayInfo); | ||
1391 | if (eError != PVRSRV_OK) | ||
1392 | { | ||
1393 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to get DC info")); | ||
1394 | return eError; | ||
1395 | } | ||
1396 | |||
1397 | psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval; | ||
1398 | psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval; | ||
1399 | |||
1400 | /* call into the display device driver to create a swapchain */ | ||
1401 | eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice, | ||
1402 | ui32Flags, | ||
1403 | psDstSurfAttrib, | ||
1404 | psSrcSurfAttrib, | ||
1405 | ui32BufferCount, | ||
1406 | apsSyncData, | ||
1407 | ui32OEMFlags, | ||
1408 | &psSwapChain->hExtSwapChain, | ||
1409 | &psSwapChain->ui32SwapChainID); | ||
1410 | if(eError != PVRSRV_OK) | ||
1411 | { | ||
1412 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Failed to create 3rd party SwapChain")); | ||
1413 | PDUMPCOMMENT("Swapchain allocation failed."); | ||
1414 | goto ErrorExit; | ||
1415 | } | ||
1416 | |||
1417 | /* Create new reference */ | ||
1418 | eError = PVRSRVCreateDCSwapChainRefKM(psPerProc, | ||
1419 | psSwapChain, | ||
1420 | &psSwapChainRef); | ||
1421 | if( eError != PVRSRV_OK ) | ||
1422 | { | ||
1423 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVCreateDCSwapChainKM: Couldn't create swap chain reference")); | ||
1424 | PDUMPCOMMENT("Swapchain allocation failed."); | ||
1425 | goto ErrorExit; | ||
1426 | } | ||
1427 | |||
1428 | psSwapChain->ui32RefCount = 1; | ||
1429 | psSwapChain->ui32Flags = ui32Flags; | ||
1430 | |||
1431 | /* Save pointer in DC structure if ti's shared struct */ | ||
1432 | if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED ) | ||
1433 | { | ||
1434 | if(! psDCInfo->psDCSwapChainShared ) | ||
1435 | { | ||
1436 | psDCInfo->psDCSwapChainShared = psSwapChain; | ||
1437 | } | ||
1438 | else | ||
1439 | { | ||
1440 | PVRSRV_DC_SWAPCHAIN *psOldHead = psDCInfo->psDCSwapChainShared; | ||
1441 | psDCInfo->psDCSwapChainShared = psSwapChain; | ||
1442 | psSwapChain->psNext = psOldHead; | ||
1443 | } | ||
1444 | } | ||
1445 | |||
1446 | /* We create swapchain - pui32SwapChainID is output */ | ||
1447 | *pui32SwapChainID = psSwapChain->ui32SwapChainID; | ||
1448 | |||
1449 | /* return the swapchain reference handle */ | ||
1450 | *phSwapChainRef= (IMG_HANDLE)psSwapChainRef; | ||
1451 | |||
1452 | return eError; | ||
1453 | |||
1454 | ErrorExit: | ||
1455 | |||
1456 | for(i=0; i<ui32BufferCount; i++) | ||
1457 | { | ||
1458 | if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) | ||
1459 | { | ||
1460 | PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); | ||
1461 | } | ||
1462 | } | ||
1463 | |||
1464 | if(psQueue) | ||
1465 | { | ||
1466 | PVRSRVDestroyCommandQueueKM(psQueue); | ||
1467 | } | ||
1468 | |||
1469 | if(psSwapChain) | ||
1470 | { | ||
1471 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL); | ||
1472 | /*not nulling pointer, out of scope*/ | ||
1473 | } | ||
1474 | |||
1475 | return eError; | ||
1476 | } | ||
1477 | |||
1478 | |||
1479 | |||
1480 | |||
1481 | IMG_EXPORT | ||
1482 | PVRSRV_ERROR PVRSRVSetDCDstRectKM(IMG_HANDLE hDeviceKM, | ||
1483 | IMG_HANDLE hSwapChainRef, | ||
1484 | IMG_RECT *psRect) | ||
1485 | { | ||
1486 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1487 | PVRSRV_DC_SWAPCHAIN *psSwapChain; | ||
1488 | |||
1489 | if(!hDeviceKM || !hSwapChainRef) | ||
1490 | { | ||
1491 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstRectKM: Invalid parameters")); | ||
1492 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1493 | } | ||
1494 | |||
1495 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1496 | psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; | ||
1497 | |||
1498 | return psDCInfo->psFuncTable->pfnSetDCDstRect(psDCInfo->hExtDevice, | ||
1499 | psSwapChain->hExtSwapChain, | ||
1500 | psRect); | ||
1501 | } | ||
1502 | |||
1503 | |||
1504 | IMG_EXPORT | ||
1505 | PVRSRV_ERROR PVRSRVSetDCSrcRectKM(IMG_HANDLE hDeviceKM, | ||
1506 | IMG_HANDLE hSwapChainRef, | ||
1507 | IMG_RECT *psRect) | ||
1508 | { | ||
1509 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1510 | PVRSRV_DC_SWAPCHAIN *psSwapChain; | ||
1511 | |||
1512 | if(!hDeviceKM || !hSwapChainRef) | ||
1513 | { | ||
1514 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcRectKM: Invalid parameters")); | ||
1515 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1516 | } | ||
1517 | |||
1518 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1519 | psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; | ||
1520 | |||
1521 | return psDCInfo->psFuncTable->pfnSetDCSrcRect(psDCInfo->hExtDevice, | ||
1522 | psSwapChain->hExtSwapChain, | ||
1523 | psRect); | ||
1524 | } | ||
1525 | |||
1526 | |||
1527 | IMG_EXPORT | ||
1528 | PVRSRV_ERROR PVRSRVSetDCDstColourKeyKM(IMG_HANDLE hDeviceKM, | ||
1529 | IMG_HANDLE hSwapChainRef, | ||
1530 | IMG_UINT32 ui32CKColour) | ||
1531 | { | ||
1532 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1533 | PVRSRV_DC_SWAPCHAIN *psSwapChain; | ||
1534 | |||
1535 | if(!hDeviceKM || !hSwapChainRef) | ||
1536 | { | ||
1537 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCDstColourKeyKM: Invalid parameters")); | ||
1538 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1539 | } | ||
1540 | |||
1541 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1542 | psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; | ||
1543 | |||
1544 | return psDCInfo->psFuncTable->pfnSetDCDstColourKey(psDCInfo->hExtDevice, | ||
1545 | psSwapChain->hExtSwapChain, | ||
1546 | ui32CKColour); | ||
1547 | } | ||
1548 | |||
1549 | |||
1550 | IMG_EXPORT | ||
1551 | PVRSRV_ERROR PVRSRVSetDCSrcColourKeyKM(IMG_HANDLE hDeviceKM, | ||
1552 | IMG_HANDLE hSwapChainRef, | ||
1553 | IMG_UINT32 ui32CKColour) | ||
1554 | { | ||
1555 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1556 | PVRSRV_DC_SWAPCHAIN *psSwapChain; | ||
1557 | |||
1558 | if(!hDeviceKM || !hSwapChainRef) | ||
1559 | { | ||
1560 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSetDCSrcColourKeyKM: Invalid parameters")); | ||
1561 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1562 | } | ||
1563 | |||
1564 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1565 | psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; | ||
1566 | |||
1567 | return psDCInfo->psFuncTable->pfnSetDCSrcColourKey(psDCInfo->hExtDevice, | ||
1568 | psSwapChain->hExtSwapChain, | ||
1569 | ui32CKColour); | ||
1570 | } | ||
1571 | |||
1572 | |||
1573 | IMG_EXPORT | ||
1574 | PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM, | ||
1575 | IMG_HANDLE hSwapChainRef, | ||
1576 | IMG_UINT32 *pui32BufferCount, | ||
1577 | IMG_HANDLE *phBuffer, | ||
1578 | IMG_SYS_PHYADDR *psPhyAddr) | ||
1579 | { | ||
1580 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1581 | PVRSRV_DC_SWAPCHAIN *psSwapChain; | ||
1582 | IMG_HANDLE ahExtBuffer[PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS]; | ||
1583 | PVRSRV_ERROR eError; | ||
1584 | IMG_UINT32 i; | ||
1585 | |||
1586 | if(!hDeviceKM || !hSwapChainRef || !phBuffer || !psPhyAddr) | ||
1587 | { | ||
1588 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters")); | ||
1589 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1590 | } | ||
1591 | |||
1592 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1593 | psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain; | ||
1594 | |||
1595 | /* call into the display device driver to get info */ | ||
1596 | eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice, | ||
1597 | psSwapChain->hExtSwapChain, | ||
1598 | pui32BufferCount, | ||
1599 | ahExtBuffer); | ||
1600 | |||
1601 | PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS); | ||
1602 | |||
1603 | /* | ||
1604 | populate the srvkm's buffer structure with the 3rd party buffer handles | ||
1605 | and return the services buffer handles | ||
1606 | */ | ||
1607 | for(i=0; i<*pui32BufferCount; i++) | ||
1608 | { | ||
1609 | psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i]; | ||
1610 | phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i]; | ||
1611 | } | ||
1612 | |||
1613 | #if defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS) | ||
1614 | for(i = 0; i < *pui32BufferCount; i++) | ||
1615 | { | ||
1616 | IMG_UINT32 ui32ByteSize, ui32TilingStride; | ||
1617 | IMG_SYS_PHYADDR *pPhyAddr; | ||
1618 | IMG_BOOL bIsContiguous; | ||
1619 | IMG_HANDLE hOSMapInfo; | ||
1620 | IMG_VOID *pvVAddr; | ||
1621 | |||
1622 | eError = psDCInfo->psFuncTable->pfnGetBufferAddr(psDCInfo->hExtDevice, | ||
1623 | ahExtBuffer[i], | ||
1624 | &pPhyAddr, | ||
1625 | &ui32ByteSize, | ||
1626 | &pvVAddr, | ||
1627 | &hOSMapInfo, | ||
1628 | &bIsContiguous, | ||
1629 | &ui32TilingStride); | ||
1630 | if(eError != PVRSRV_OK) | ||
1631 | { | ||
1632 | break; | ||
1633 | } | ||
1634 | |||
1635 | psPhyAddr[i] = *pPhyAddr; | ||
1636 | } | ||
1637 | #endif /* defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS) */ | ||
1638 | |||
1639 | return eError; | ||
1640 | } | ||
1641 | |||
1642 | |||
1643 | IMG_EXPORT | ||
1644 | PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM, | ||
1645 | IMG_HANDLE hBuffer, | ||
1646 | IMG_UINT32 ui32SwapInterval, | ||
1647 | IMG_HANDLE hPrivateTag, | ||
1648 | IMG_UINT32 ui32ClipRectCount, | ||
1649 | IMG_RECT *psClipRect) | ||
1650 | { | ||
1651 | PVRSRV_ERROR eError; | ||
1652 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1653 | PVRSRV_DC_BUFFER *psBuffer; | ||
1654 | PVRSRV_QUEUE_INFO *psQueue; | ||
1655 | DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; | ||
1656 | IMG_UINT32 i; | ||
1657 | IMG_BOOL bAddReferenceToLast = IMG_TRUE; | ||
1658 | IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND; | ||
1659 | IMG_UINT32 ui32NumSrcSyncs = 1; | ||
1660 | PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2]; | ||
1661 | PVRSRV_COMMAND *psCommand; | ||
1662 | SYS_DATA *psSysData; | ||
1663 | |||
1664 | if(!hDeviceKM || !hBuffer || !psClipRect) | ||
1665 | { | ||
1666 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid parameters")); | ||
1667 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1668 | } | ||
1669 | |||
1670 | psBuffer = (PVRSRV_DC_BUFFER*)hBuffer; | ||
1671 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1672 | |||
1673 | /* Validate swap interval against limits */ | ||
1674 | if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval || | ||
1675 | ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval) | ||
1676 | { | ||
1677 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Invalid swap interval. Requested %u, Allowed range %u-%u", | ||
1678 | ui32SwapInterval, psBuffer->psSwapChain->ui32MinSwapInterval, psBuffer->psSwapChain->ui32MaxSwapInterval)); | ||
1679 | return PVRSRV_ERROR_INVALID_SWAPINTERVAL; | ||
1680 | } | ||
1681 | |||
1682 | #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) | ||
1683 | |||
1684 | if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL) | ||
1685 | { | ||
1686 | psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice, | ||
1687 | psBuffer->psSwapChain->hExtSwapChain, | ||
1688 | psBuffer->sDeviceClassBuffer.hExtBuffer, | ||
1689 | hPrivateTag, | ||
1690 | &ui16SwapCommandID, | ||
1691 | &bAddReferenceToLast); | ||
1692 | |||
1693 | } | ||
1694 | |||
1695 | #endif | ||
1696 | |||
1697 | /* get the queue from the buffer structure */ | ||
1698 | psQueue = psBuffer->psSwapChain->psQueue; | ||
1699 | |||
1700 | /* specify the syncs */ | ||
1701 | apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo; | ||
1702 | if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer && | ||
1703 | psBuffer != psBuffer->psSwapChain->psLastFlipBuffer) | ||
1704 | { | ||
1705 | apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo; | ||
1706 | ui32NumSrcSyncs++; | ||
1707 | } | ||
1708 | |||
1709 | /* insert the command (header) */ | ||
1710 | eError = PVRSRVInsertCommandKM (psQueue, | ||
1711 | &psCommand, | ||
1712 | psDCInfo->ui32DeviceID, | ||
1713 | ui16SwapCommandID, | ||
1714 | 0, | ||
1715 | IMG_NULL, | ||
1716 | ui32NumSrcSyncs, | ||
1717 | apsSrcSync, | ||
1718 | sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount), | ||
1719 | IMG_NULL, | ||
1720 | IMG_NULL); | ||
1721 | if(eError != PVRSRV_OK) | ||
1722 | { | ||
1723 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue")); | ||
1724 | goto Exit; | ||
1725 | } | ||
1726 | |||
1727 | /* setup the flip command */ | ||
1728 | psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData; | ||
1729 | |||
1730 | /* Ext Device Handle */ | ||
1731 | psFlipCmd->hExtDevice = psDCInfo->hExtDevice; | ||
1732 | |||
1733 | /* Ext SwapChain Handle */ | ||
1734 | psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain; | ||
1735 | |||
1736 | /* Ext Buffer Handle (Buffer to Flip to) */ | ||
1737 | psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer; | ||
1738 | |||
1739 | /* private tag */ | ||
1740 | psFlipCmd->hPrivateTag = hPrivateTag; | ||
1741 | |||
1742 | /* setup the clip rects */ | ||
1743 | psFlipCmd->ui32ClipRectCount = ui32ClipRectCount; | ||
1744 | /* cliprect memory appends the command structure */ | ||
1745 | psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND)); // PRQA S 3305 | ||
1746 | /* copy the clip rects */ | ||
1747 | for(i=0; i<ui32ClipRectCount; i++) | ||
1748 | { | ||
1749 | psFlipCmd->psClipRect[i] = psClipRect[i]; | ||
1750 | } | ||
1751 | |||
1752 | /* number of vsyncs between successive flips */ | ||
1753 | psFlipCmd->ui32SwapInterval = ui32SwapInterval; | ||
1754 | |||
1755 | SysAcquireData(&psSysData); | ||
1756 | |||
1757 | /* Because we might be composing just software surfaces, without | ||
1758 | * any SGX renders since the last frame, we won't necessarily | ||
1759 | * have cleaned/flushed the CPU caches before the buffers need | ||
1760 | * to be displayed. | ||
1761 | * | ||
1762 | * Doing so now is safe because InsertCommand bumped ROP2 on the | ||
1763 | * affected buffers (preventing more SW renders starting) but the | ||
1764 | * display won't start to process the buffers until SubmitCommand. | ||
1765 | */ | ||
1766 | { | ||
1767 | if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) | ||
1768 | { | ||
1769 | OSFlushCPUCacheKM(); | ||
1770 | } | ||
1771 | else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) | ||
1772 | { | ||
1773 | OSCleanCPUCacheKM(); | ||
1774 | } | ||
1775 | |||
1776 | psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE; | ||
1777 | } | ||
1778 | |||
1779 | /* submit the command */ | ||
1780 | eError = PVRSRVSubmitCommandKM (psQueue, psCommand); | ||
1781 | if (eError != PVRSRV_OK) | ||
1782 | { | ||
1783 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to submit command")); | ||
1784 | goto Exit; | ||
1785 | } | ||
1786 | |||
1787 | /* | ||
1788 | Schedule an MISR to process it | ||
1789 | */ | ||
1790 | eError = OSScheduleMISR(psSysData); | ||
1791 | |||
1792 | if (eError != PVRSRV_OK) | ||
1793 | { | ||
1794 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to schedule MISR")); | ||
1795 | goto Exit; | ||
1796 | } | ||
1797 | |||
1798 | /* update the last flip buffer */ | ||
1799 | psBuffer->psSwapChain->psLastFlipBuffer = psBuffer; | ||
1800 | |||
1801 | Exit: | ||
1802 | |||
1803 | if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) | ||
1804 | { | ||
1805 | eError = PVRSRV_ERROR_RETRY; | ||
1806 | } | ||
1807 | |||
1808 | return eError; | ||
1809 | } | ||
1810 | |||
1811 | typedef struct _CALLBACK_DATA_ | ||
1812 | { | ||
1813 | IMG_PVOID pvPrivData; | ||
1814 | IMG_UINT32 ui32PrivDataLength; | ||
1815 | IMG_PVOID ppvMemInfos; | ||
1816 | IMG_UINT32 ui32NumMemInfos; | ||
1817 | } CALLBACK_DATA; | ||
1818 | |||
1819 | static IMG_VOID FreePrivateData(IMG_HANDLE hCallbackData) | ||
1820 | { | ||
1821 | CALLBACK_DATA *psCallbackData = hCallbackData; | ||
1822 | |||
1823 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psCallbackData->ui32PrivDataLength, | ||
1824 | psCallbackData->pvPrivData, IMG_NULL); | ||
1825 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
1826 | sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos, | ||
1827 | psCallbackData->ppvMemInfos, IMG_NULL); | ||
1828 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), hCallbackData, IMG_NULL); | ||
1829 | } | ||
1830 | |||
1831 | IMG_EXPORT | ||
1832 | PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM, | ||
1833 | IMG_HANDLE hSwapChain, | ||
1834 | IMG_UINT32 ui32SwapInterval, | ||
1835 | PVRSRV_KERNEL_MEM_INFO **ppsMemInfos, | ||
1836 | PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos, | ||
1837 | IMG_UINT32 ui32NumMemSyncInfos, | ||
1838 | IMG_PVOID pvPrivData, | ||
1839 | IMG_UINT32 ui32PrivDataLength) | ||
1840 | { | ||
1841 | PVRSRV_KERNEL_SYNC_INFO **ppsCompiledSyncInfos; | ||
1842 | IMG_UINT32 i, ui32NumCompiledSyncInfos; | ||
1843 | DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd; | ||
1844 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
1845 | PVRSRV_DC_SWAPCHAIN *psSwapChain; | ||
1846 | PVRSRV_ERROR eError = PVRSRV_OK; | ||
1847 | CALLBACK_DATA *psCallbackData; | ||
1848 | PVRSRV_QUEUE_INFO *psQueue; | ||
1849 | PVRSRV_COMMAND *psCommand; | ||
1850 | IMG_PVOID *ppvMemInfos; | ||
1851 | SYS_DATA *psSysData; | ||
1852 | |||
1853 | if(!hDeviceKM || !hSwapChain || !ppsMemInfos || !ppsSyncInfos || ui32NumMemSyncInfos < 1) | ||
1854 | { | ||
1855 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid parameters")); | ||
1856 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
1857 | } | ||
1858 | |||
1859 | psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChain)->psSwapChain; | ||
1860 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
1861 | |||
1862 | /* Validate swap interval against limits */ | ||
1863 | if(ui32SwapInterval < psSwapChain->ui32MinSwapInterval || | ||
1864 | ui32SwapInterval > psSwapChain->ui32MaxSwapInterval) | ||
1865 | { | ||
1866 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid swap interval. Requested %u, Allowed range %u-%u", | ||
1867 | ui32SwapInterval, psSwapChain->ui32MinSwapInterval, psSwapChain->ui32MaxSwapInterval)); | ||
1868 | return PVRSRV_ERROR_INVALID_SWAPINTERVAL; | ||
1869 | } | ||
1870 | |||
1871 | eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
1872 | sizeof(CALLBACK_DATA), | ||
1873 | (IMG_VOID **)&psCallbackData, IMG_NULL, | ||
1874 | "PVRSRVSwapToDCBuffer2KM callback data"); | ||
1875 | if (eError != PVRSRV_OK) | ||
1876 | { | ||
1877 | return eError; | ||
1878 | } | ||
1879 | |||
1880 | psCallbackData->pvPrivData = pvPrivData; | ||
1881 | psCallbackData->ui32PrivDataLength = ui32PrivDataLength; | ||
1882 | |||
1883 | if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
1884 | sizeof(IMG_VOID *) * ui32NumMemSyncInfos, | ||
1885 | (IMG_VOID **)&ppvMemInfos, IMG_NULL, | ||
1886 | "Swap Command Meminfos") != PVRSRV_OK) | ||
1887 | { | ||
1888 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list")); | ||
1889 | psCallbackData->ppvMemInfos = IMG_NULL; | ||
1890 | goto Exit; | ||
1891 | } | ||
1892 | |||
1893 | for(i = 0; i < ui32NumMemSyncInfos; i++) | ||
1894 | { | ||
1895 | ppvMemInfos[i] = ppsMemInfos[i]; | ||
1896 | } | ||
1897 | |||
1898 | psCallbackData->ppvMemInfos = ppvMemInfos; | ||
1899 | psCallbackData->ui32NumMemInfos = ui32NumMemSyncInfos; | ||
1900 | |||
1901 | /* get the queue from the buffer structure */ | ||
1902 | psQueue = psSwapChain->psQueue; | ||
1903 | |||
1904 | #if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) | ||
1905 | if(psSwapChain->ppsLastSyncInfos) | ||
1906 | { | ||
1907 | IMG_UINT32 ui32NumUniqueSyncInfos = psSwapChain->ui32LastNumSyncInfos; | ||
1908 | IMG_UINT32 j; | ||
1909 | |||
1910 | for(j = 0; j < psSwapChain->ui32LastNumSyncInfos; j++) | ||
1911 | { | ||
1912 | for(i = 0; i < ui32NumMemSyncInfos; i++) | ||
1913 | { | ||
1914 | if(psSwapChain->ppsLastSyncInfos[j] == ppsSyncInfos[i]) | ||
1915 | { | ||
1916 | psSwapChain->ppsLastSyncInfos[j] = IMG_NULL; | ||
1917 | ui32NumUniqueSyncInfos--; | ||
1918 | } | ||
1919 | } | ||
1920 | } | ||
1921 | |||
1922 | ui32NumCompiledSyncInfos = ui32NumMemSyncInfos + ui32NumUniqueSyncInfos; | ||
1923 | |||
1924 | if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
1925 | sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos, | ||
1926 | (IMG_VOID **)&ppsCompiledSyncInfos, IMG_NULL, | ||
1927 | "Compiled syncinfos") != PVRSRV_OK) | ||
1928 | { | ||
1929 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list")); | ||
1930 | goto Exit; | ||
1931 | } | ||
1932 | |||
1933 | OSMemCopy(ppsCompiledSyncInfos, ppsSyncInfos, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos); | ||
1934 | for(j = 0, i = ui32NumMemSyncInfos; j < psSwapChain->ui32LastNumSyncInfos; j++) | ||
1935 | { | ||
1936 | if(psSwapChain->ppsLastSyncInfos[j]) | ||
1937 | { | ||
1938 | ppsCompiledSyncInfos[i] = psSwapChain->ppsLastSyncInfos[j]; | ||
1939 | i++; | ||
1940 | } | ||
1941 | } | ||
1942 | } | ||
1943 | else | ||
1944 | #endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */ | ||
1945 | { | ||
1946 | ppsCompiledSyncInfos = ppsSyncInfos; | ||
1947 | ui32NumCompiledSyncInfos = ui32NumMemSyncInfos; | ||
1948 | } | ||
1949 | |||
1950 | /* insert the command (header) */ | ||
1951 | eError = PVRSRVInsertCommandKM (psQueue, | ||
1952 | &psCommand, | ||
1953 | psDCInfo->ui32DeviceID, | ||
1954 | DC_FLIP_COMMAND, | ||
1955 | 0, | ||
1956 | IMG_NULL, | ||
1957 | ui32NumCompiledSyncInfos, | ||
1958 | ppsCompiledSyncInfos, | ||
1959 | sizeof(DISPLAYCLASS_FLIP_COMMAND2), | ||
1960 | FreePrivateData, | ||
1961 | psCallbackData); | ||
1962 | |||
1963 | if (ppsCompiledSyncInfos != ppsSyncInfos) | ||
1964 | { | ||
1965 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
1966 | sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos, | ||
1967 | (IMG_VOID *)ppsCompiledSyncInfos, | ||
1968 | IMG_NULL); | ||
1969 | } | ||
1970 | if(eError != PVRSRV_OK) | ||
1971 | { | ||
1972 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to get space in queue")); | ||
1973 | goto Exit; | ||
1974 | } | ||
1975 | |||
1976 | /* setup the flip command */ | ||
1977 | psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND2*)psCommand->pvData; | ||
1978 | |||
1979 | /* Ext Device Handle */ | ||
1980 | psFlipCmd->hExtDevice = psDCInfo->hExtDevice; | ||
1981 | |||
1982 | /* Ext SwapChain Handle */ | ||
1983 | psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain; | ||
1984 | |||
1985 | /* number of vsyncs between successive flips */ | ||
1986 | psFlipCmd->ui32SwapInterval = ui32SwapInterval; | ||
1987 | |||
1988 | /* Opaque private data, if supplied */ | ||
1989 | psFlipCmd->pvPrivData = pvPrivData; | ||
1990 | psFlipCmd->ui32PrivDataLength = ui32PrivDataLength; | ||
1991 | |||
1992 | psFlipCmd->ppsMemInfos = (PDC_MEM_INFO *)ppvMemInfos; | ||
1993 | psFlipCmd->ui32NumMemInfos = ui32NumMemSyncInfos; | ||
1994 | |||
1995 | /* Even though this is "unused", we have to initialize it, | ||
1996 | * as the display controller might NULL-test it. | ||
1997 | */ | ||
1998 | psFlipCmd->hUnused = IMG_NULL; | ||
1999 | |||
2000 | SysAcquireData(&psSysData); | ||
2001 | |||
2002 | /* Because we might be composing just software surfaces, without | ||
2003 | * any SGX renders since the last frame, we won't necessarily | ||
2004 | * have cleaned/flushed the CPU caches before the buffers need | ||
2005 | * to be displayed. | ||
2006 | * | ||
2007 | * Doing so now is safe because InsertCommand bumped ROP2 on the | ||
2008 | * affected buffers (preventing more SW renders starting) but the | ||
2009 | * display won't start to process the buffers until SubmitCommand. | ||
2010 | */ | ||
2011 | { | ||
2012 | if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH) | ||
2013 | { | ||
2014 | OSFlushCPUCacheKM(); | ||
2015 | } | ||
2016 | else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN) | ||
2017 | { | ||
2018 | OSCleanCPUCacheKM(); | ||
2019 | } | ||
2020 | |||
2021 | psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE; | ||
2022 | } | ||
2023 | |||
2024 | /* submit the command */ | ||
2025 | eError = PVRSRVSubmitCommandKM (psQueue, psCommand); | ||
2026 | if (eError != PVRSRV_OK) | ||
2027 | { | ||
2028 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to submit command")); | ||
2029 | goto Exit; | ||
2030 | } | ||
2031 | |||
2032 | /* The command has been submitted and so psCallbackData will be freed by the callback */ | ||
2033 | psCallbackData = IMG_NULL; | ||
2034 | |||
2035 | /* | ||
2036 | Schedule an MISR to process it | ||
2037 | */ | ||
2038 | eError = OSScheduleMISR(psSysData); | ||
2039 | |||
2040 | if (eError != PVRSRV_OK) | ||
2041 | { | ||
2042 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to schedule MISR")); | ||
2043 | goto Exit; | ||
2044 | } | ||
2045 | |||
2046 | #if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) | ||
2047 | /* Reallocate the syncinfo list if it was too small */ | ||
2048 | if (psSwapChain->ui32LastNumSyncInfos < ui32NumMemSyncInfos) | ||
2049 | { | ||
2050 | if (psSwapChain->ppsLastSyncInfos) | ||
2051 | { | ||
2052 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos, | ||
2053 | psSwapChain->ppsLastSyncInfos, IMG_NULL); | ||
2054 | } | ||
2055 | |||
2056 | if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
2057 | sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos, | ||
2058 | (IMG_VOID **)&psSwapChain->ppsLastSyncInfos, IMG_NULL, | ||
2059 | "Last syncinfos") != PVRSRV_OK) | ||
2060 | { | ||
2061 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list")); | ||
2062 | goto Exit; | ||
2063 | } | ||
2064 | } | ||
2065 | |||
2066 | psSwapChain->ui32LastNumSyncInfos = ui32NumMemSyncInfos; | ||
2067 | |||
2068 | for(i = 0; i < ui32NumMemSyncInfos; i++) | ||
2069 | { | ||
2070 | psSwapChain->ppsLastSyncInfos[i] = ppsSyncInfos[i]; | ||
2071 | } | ||
2072 | #endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */ | ||
2073 | |||
2074 | Exit: | ||
2075 | if (psCallbackData) | ||
2076 | { | ||
2077 | if(psCallbackData->ppvMemInfos) | ||
2078 | { | ||
2079 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
2080 | sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos, | ||
2081 | psCallbackData->ppvMemInfos, IMG_NULL); | ||
2082 | } | ||
2083 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), psCallbackData, IMG_NULL); | ||
2084 | } | ||
2085 | if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) | ||
2086 | { | ||
2087 | eError = PVRSRV_ERROR_RETRY; | ||
2088 | } | ||
2089 | |||
2090 | return eError; | ||
2091 | } | ||
2092 | |||
2093 | |||
2094 | IMG_EXPORT | ||
2095 | PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM, | ||
2096 | IMG_HANDLE hSwapChainRef) | ||
2097 | { | ||
2098 | PVRSRV_ERROR eError; | ||
2099 | PVRSRV_QUEUE_INFO *psQueue; | ||
2100 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
2101 | PVRSRV_DC_SWAPCHAIN *psSwapChain; | ||
2102 | PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef; | ||
2103 | DISPLAYCLASS_FLIP_COMMAND *psFlipCmd; | ||
2104 | IMG_UINT32 ui32NumSrcSyncs = 1; | ||
2105 | PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[2]; | ||
2106 | PVRSRV_COMMAND *psCommand; | ||
2107 | IMG_BOOL bAddReferenceToLast = IMG_TRUE; | ||
2108 | IMG_UINT16 ui16SwapCommandID = DC_FLIP_COMMAND; | ||
2109 | SYS_DATA *psSysData; | ||
2110 | |||
2111 | if(!hDeviceKM || !hSwapChainRef) | ||
2112 | { | ||
2113 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Invalid parameters")); | ||
2114 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
2115 | } | ||
2116 | |||
2117 | psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM); | ||
2118 | psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef; | ||
2119 | psSwapChain = psSwapChainRef->psSwapChain; | ||
2120 | |||
2121 | /* | ||
2122 | If more then 1 reference to the swapchain exist then | ||
2123 | ignore any request to swap to the system buffer | ||
2124 | */ | ||
2125 | if (psSwapChain->ui32RefCount > 1) | ||
2126 | { | ||
2127 | return PVRSRV_OK; | ||
2128 | } | ||
2129 | |||
2130 | /* get the queue from the buffer structure */ | ||
2131 | psQueue = psSwapChain->psQueue; | ||
2132 | |||
2133 | #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) | ||
2134 | |||
2135 | if(psDCInfo->psFuncTable->pfnQuerySwapCommandID != IMG_NULL) | ||
2136 | { | ||
2137 | psDCInfo->psFuncTable->pfnQuerySwapCommandID(psDCInfo->hExtDevice, | ||
2138 | psSwapChain->hExtSwapChain, | ||
2139 | psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer, | ||
2140 | 0, | ||
2141 | &ui16SwapCommandID, | ||
2142 | &bAddReferenceToLast); | ||
2143 | |||
2144 | } | ||
2145 | |||
2146 | #endif | ||
2147 | |||
2148 | /* specify the syncs */ | ||
2149 | apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo; | ||
2150 | if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer) | ||
2151 | { | ||
2152 | /* Make sure we don't make a double dependency on the same server */ | ||
2153 | if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo) | ||
2154 | { | ||
2155 | apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo; | ||
2156 | ui32NumSrcSyncs++; | ||
2157 | } | ||
2158 | } | ||
2159 | |||
2160 | /* insert the command (header) */ | ||
2161 | eError = PVRSRVInsertCommandKM (psQueue, | ||
2162 | &psCommand, | ||
2163 | psDCInfo->ui32DeviceID, | ||
2164 | ui16SwapCommandID, | ||
2165 | 0, | ||
2166 | IMG_NULL, | ||
2167 | ui32NumSrcSyncs, | ||
2168 | apsSrcSync, | ||
2169 | sizeof(DISPLAYCLASS_FLIP_COMMAND), | ||
2170 | IMG_NULL, | ||
2171 | IMG_NULL); | ||
2172 | if(eError != PVRSRV_OK) | ||
2173 | { | ||
2174 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue")); | ||
2175 | goto Exit; | ||
2176 | } | ||
2177 | |||
2178 | /* setup the flip command */ | ||
2179 | psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData; | ||
2180 | |||
2181 | /* Ext Device Handle */ | ||
2182 | psFlipCmd->hExtDevice = psDCInfo->hExtDevice; | ||
2183 | |||
2184 | /* Ext SwapChain Handle */ | ||
2185 | psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain; | ||
2186 | |||
2187 | /* Ext Buffer Handle (Buffer to Flip to) */ | ||
2188 | psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer; | ||
2189 | |||
2190 | /* private tag */ | ||
2191 | psFlipCmd->hPrivateTag = IMG_NULL; | ||
2192 | |||
2193 | /* setup the clip rects */ | ||
2194 | psFlipCmd->ui32ClipRectCount = 0; | ||
2195 | |||
2196 | psFlipCmd->ui32SwapInterval = 1; | ||
2197 | |||
2198 | /* submit the command */ | ||
2199 | eError = PVRSRVSubmitCommandKM (psQueue, psCommand); | ||
2200 | if (eError != PVRSRV_OK) | ||
2201 | { | ||
2202 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to submit command")); | ||
2203 | goto Exit; | ||
2204 | } | ||
2205 | |||
2206 | /* Schedule an MISR to process it */ | ||
2207 | SysAcquireData(&psSysData); | ||
2208 | eError = OSScheduleMISR(psSysData); | ||
2209 | |||
2210 | if (eError != PVRSRV_OK) | ||
2211 | { | ||
2212 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to schedule MISR")); | ||
2213 | goto Exit; | ||
2214 | } | ||
2215 | |||
2216 | /* update the last flip buffer */ | ||
2217 | psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer; | ||
2218 | |||
2219 | eError = PVRSRV_OK; | ||
2220 | |||
2221 | Exit: | ||
2222 | |||
2223 | if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE) | ||
2224 | { | ||
2225 | eError = PVRSRV_ERROR_RETRY; | ||
2226 | } | ||
2227 | |||
2228 | return eError; | ||
2229 | } | ||
2230 | |||
2231 | |||
2232 | /*! | ||
2233 | ****************************************************************************** | ||
2234 | |||
2235 | @Function PVRSRVRegisterSystemISRHandler | ||
2236 | |||
2237 | @Description | ||
2238 | |||
2239 | registers an external ISR to be called of the back of a system ISR | ||
2240 | |||
2241 | @Input ppfnISRHandler : ISR pointer | ||
2242 | |||
2243 | @Input hISRHandlerData : Callback data | ||
2244 | |||
2245 | @Input ui32ISRSourceMask : ISR Mask | ||
2246 | |||
2247 | @Input ui32DeviceID : unique device key | ||
2248 | |||
2249 | @Return PVRSRV_ERROR : | ||
2250 | |||
2251 | ******************************************************************************/ | ||
2252 | static | ||
2253 | PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler, | ||
2254 | IMG_VOID *pvISRHandlerData, | ||
2255 | IMG_UINT32 ui32ISRSourceMask, | ||
2256 | IMG_UINT32 ui32DeviceID) | ||
2257 | { | ||
2258 | SYS_DATA *psSysData; | ||
2259 | PVRSRV_DEVICE_NODE *psDevNode; | ||
2260 | |||
2261 | PVR_UNREFERENCED_PARAMETER(ui32ISRSourceMask); | ||
2262 | |||
2263 | SysAcquireData(&psSysData); | ||
2264 | |||
2265 | /* Find Dev Node (just using the device id, ignore the class) */ | ||
2266 | psDevNode = (PVRSRV_DEVICE_NODE*) | ||
2267 | List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, | ||
2268 | &MatchDeviceKM_AnyVaCb, | ||
2269 | ui32DeviceID, | ||
2270 | IMG_TRUE); | ||
2271 | |||
2272 | if (psDevNode == IMG_NULL) | ||
2273 | { | ||
2274 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterSystemISRHandler: Failed to get psDevNode")); | ||
2275 | PVR_DBG_BREAK; | ||
2276 | return PVRSRV_ERROR_NO_DEVICENODE_FOUND; | ||
2277 | } | ||
2278 | |||
2279 | /* set up data before enabling the ISR */ | ||
2280 | psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData; | ||
2281 | |||
2282 | /* enable the ISR */ | ||
2283 | psDevNode->pfnDeviceISR = pfnISRHandler; | ||
2284 | |||
2285 | return PVRSRV_OK; | ||
2286 | } | ||
2287 | |||
2288 | /*! | ||
2289 | ****************************************************************************** | ||
2290 | |||
2291 | @Function PVRSRVSetDCState_ForEachVaCb | ||
2292 | |||
2293 | @Description | ||
2294 | |||
2295 | If the device node is a display, calls its set state function. | ||
2296 | |||
2297 | @Input psDeviceNode - the device node | ||
2298 | va - variable argument list with: | ||
2299 | ui32State - the state to be set. | ||
2300 | |||
2301 | ******************************************************************************/ | ||
2302 | static | ||
2303 | IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va) | ||
2304 | { | ||
2305 | PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
2306 | IMG_UINT32 ui32State; | ||
2307 | ui32State = va_arg(va, IMG_UINT32); | ||
2308 | |||
2309 | if (psDeviceNode->sDevId.eDeviceClass == PVRSRV_DEVICE_CLASS_DISPLAY) | ||
2310 | { | ||
2311 | psDCInfo = (PVRSRV_DISPLAYCLASS_INFO *)psDeviceNode->pvDevice; | ||
2312 | if (psDCInfo->psFuncTable->pfnSetDCState && psDCInfo->hExtDevice) | ||
2313 | { | ||
2314 | psDCInfo->psFuncTable->pfnSetDCState(psDCInfo->hExtDevice, ui32State); | ||
2315 | } | ||
2316 | } | ||
2317 | } | ||
2318 | |||
2319 | |||
2320 | /*! | ||
2321 | ****************************************************************************** | ||
2322 | |||
2323 | @Function PVRSRVSetDCState | ||
2324 | |||
2325 | @Description | ||
2326 | |||
2327 | Calls the display driver(s) to put them into the specified state. | ||
2328 | |||
2329 | @Input ui32State: new DC state - one of DC_STATE_* | ||
2330 | |||
2331 | ******************************************************************************/ | ||
2332 | IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State) | ||
2333 | { | ||
2334 | /* PVRSRV_DISPLAYCLASS_INFO *psDCInfo; | ||
2335 | PVRSRV_DEVICE_NODE *psDeviceNode; */ | ||
2336 | SYS_DATA *psSysData; | ||
2337 | |||
2338 | SysAcquireData(&psSysData); | ||
2339 | |||
2340 | List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList, | ||
2341 | &PVRSRVSetDCState_ForEachVaCb, | ||
2342 | ui32State); | ||
2343 | } | ||
2344 | |||
2345 | static PVRSRV_ERROR | ||
2346 | PVRSRVDCMemInfoGetCpuVAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, | ||
2347 | IMG_CPU_VIRTADDR *pVAddr) | ||
2348 | { | ||
2349 | *pVAddr = psKernelMemInfo->pvLinAddrKM; | ||
2350 | return PVRSRV_OK; | ||
2351 | } | ||
2352 | |||
2353 | static PVRSRV_ERROR | ||
2354 | PVRSRVDCMemInfoGetCpuPAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, | ||
2355 | IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr) | ||
2356 | { | ||
2357 | *pPAddr = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uByteOffset); | ||
2358 | return PVRSRV_OK; | ||
2359 | } | ||
2360 | |||
2361 | static PVRSRV_ERROR | ||
2362 | PVRSRVDCMemInfoGetByteSize(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, | ||
2363 | IMG_SIZE_T *uByteSize) | ||
2364 | { | ||
2365 | *uByteSize = psKernelMemInfo->uAllocSize; | ||
2366 | return PVRSRV_OK; | ||
2367 | } | ||
2368 | |||
2369 | static IMG_BOOL | ||
2370 | PVRSRVDCMemInfoIsPhysContig(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo) | ||
2371 | { | ||
2372 | return OSMemHandleIsPhysContig(psKernelMemInfo->sMemBlk.hOSMemHandle); | ||
2373 | } | ||
2374 | |||
2375 | static PVRSRV_ERROR PVRSRVDCMemInfoGetBvHandle(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, IMG_VOID **handle) | ||
2376 | { | ||
2377 | #if !defined(CONFIG_GCBV) | ||
2378 | *handle = NULL; | ||
2379 | return PVRSRV_ERROR_NOT_SUPPORTED; | ||
2380 | #else | ||
2381 | *handle = gc_meminfo_to_hndl(psKernelMemInfo); | ||
2382 | return PVRSRV_OK; | ||
2383 | #endif | ||
2384 | } | ||
2385 | |||
2386 | /*! | ||
2387 | ****************************************************************************** | ||
2388 | |||
2389 | @Function PVRSRVDCMemInfoGetCpuMultiPlanePAddr | ||
2390 | |||
2391 | @Description returns physical addresses of a multi-plane buffer | ||
2392 | |||
2393 | |||
2394 | @Input psKernelMemInfo - Pointer to Kernel Memory Info structure | ||
2395 | puPlaneByteOffsets - requested offset inside the plane. | ||
2396 | If the array is a NULL pointer, 0 requested offsets | ||
2397 | are assumed for all planes; | ||
2398 | pui32NumAddrOffsets - specifying the size of the user array. | ||
2399 | If the array is smaller than the number of the planes | ||
2400 | for this buffer, the correct size will be set and an | ||
2401 | error returned back; | ||
2402 | |||
2403 | @Output pPlanePAddrs - array of plane physical addresses of the returned size | ||
2404 | in pui32NumAddrOffsets; | ||
2405 | pui32NumAddrOffsets - contains the real number of planes for the buffer; | ||
2406 | |||
2407 | @Return IMG_INT32 : size of the entire buffer or negative number on ERROR | ||
2408 | |||
2409 | ******************************************************************************/ | ||
2410 | static IMG_INT32 | ||
2411 | PVRSRVDCMemInfoGetCpuMultiPlanePAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo, | ||
2412 | IMG_SIZE_T* puPlaneByteOffsets, IMG_CPU_PHYADDR* pPlanePAddrs, | ||
2413 | IMG_UINT32* pui32NumAddrOffsets) | ||
2414 | { | ||
2415 | IMG_UINT32 aui32PlaneAddressOffsets[PVRSRV_MAX_NUMBER_OF_MM_BUFFER_PLANES]; | ||
2416 | IMG_INT32 i32Ret; | ||
2417 | IMG_UINT32 i; | ||
2418 | |||
2419 | i32Ret = OSGetMemMultiPlaneInfo(psKernelMemInfo->sMemBlk.hOSMemHandle, | ||
2420 | aui32PlaneAddressOffsets, | ||
2421 | pui32NumAddrOffsets); | ||
2422 | |||
2423 | if((i32Ret < 0) || (pPlanePAddrs == IMG_NULL)) | ||
2424 | return i32Ret; | ||
2425 | |||
2426 | for (i = 0; i < *pui32NumAddrOffsets; i++) | ||
2427 | { | ||
2428 | IMG_SIZE_T uiReqByteOffsets = puPlaneByteOffsets ? puPlaneByteOffsets[i] : 0; | ||
2429 | |||
2430 | uiReqByteOffsets += aui32PlaneAddressOffsets[i]; | ||
2431 | |||
2432 | pPlanePAddrs[i] = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uiReqByteOffsets); | ||
2433 | } | ||
2434 | |||
2435 | return i32Ret; | ||
2436 | } | ||
2437 | |||
2438 | /*! | ||
2439 | ****************************************************************************** | ||
2440 | |||
2441 | @Function PVRGetDisplayClassJTable | ||
2442 | |||
2443 | @Description | ||
2444 | |||
2445 | Sets up function table for 3rd party Display Class Device to call through | ||
2446 | |||
2447 | @Input psJTable : pointer to function pointer table memory | ||
2448 | |||
2449 | @Return PVRSRV_ERROR : | ||
2450 | |||
2451 | ******************************************************************************/ | ||
2452 | IMG_EXPORT | ||
2453 | IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable) | ||
2454 | { | ||
2455 | psJTable->ui32TableSize = sizeof(PVRSRV_DC_DISP2SRV_KMJTABLE); | ||
2456 | psJTable->pfnPVRSRVRegisterDCDevice = &PVRSRVRegisterDCDeviceKM; | ||
2457 | psJTable->pfnPVRSRVRemoveDCDevice = &PVRSRVRemoveDCDeviceKM; | ||
2458 | psJTable->pfnPVRSRVOEMFunction = &SysOEMFunction; | ||
2459 | psJTable->pfnPVRSRVRegisterCmdProcList = &PVRSRVRegisterCmdProcListKM; | ||
2460 | psJTable->pfnPVRSRVRemoveCmdProcList = &PVRSRVRemoveCmdProcListKM; | ||
2461 | #if defined(SUPPORT_MISR_IN_THREAD) | ||
2462 | psJTable->pfnPVRSRVCmdComplete = &OSVSyncMISR; | ||
2463 | #else | ||
2464 | psJTable->pfnPVRSRVCmdComplete = &PVRSRVCommandCompleteKM; | ||
2465 | #endif | ||
2466 | psJTable->pfnPVRSRVRegisterSystemISRHandler = &PVRSRVRegisterSystemISRHandler; | ||
2467 | psJTable->pfnPVRSRVRegisterPowerDevice = &PVRSRVRegisterPowerDevice; | ||
2468 | #if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS) | ||
2469 | psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM; | ||
2470 | #endif | ||
2471 | psJTable->pfnPVRSRVDCMemInfoGetCpuVAddr = &PVRSRVDCMemInfoGetCpuVAddr; | ||
2472 | psJTable->pfnPVRSRVDCMemInfoGetCpuPAddr = &PVRSRVDCMemInfoGetCpuPAddr; | ||
2473 | psJTable->pfnPVRSRVDCMemInfoGetByteSize = &PVRSRVDCMemInfoGetByteSize; | ||
2474 | psJTable->pfnPVRSRVDCMemInfoIsPhysContig = &PVRSRVDCMemInfoIsPhysContig; | ||
2475 | psJTable->pfnPVRSRVDCMemInfoGetBvHandle = &PVRSRVDCMemInfoGetBvHandle; | ||
2476 | psJTable->pfnPVRSRVDCMemInfoGetCpuMultiPlanePAddr = PVRSRVDCMemInfoGetCpuMultiPlanePAddr; | ||
2477 | return IMG_TRUE; | ||
2478 | } | ||
2479 | |||
2480 | |||
2481 | |||
2482 | /****************************************************************************** | ||
2483 | |||
2484 | @Function PVRSRVCloseBCDeviceKM | ||
2485 | |||
2486 | @Description | ||
2487 | |||
2488 | Closes a connection to the Buffer Class device | ||
2489 | |||
2490 | @Input hDeviceKM : device handle | ||
2491 | |||
2492 | @Return PVRSRV_ERROR : | ||
2493 | |||
2494 | ******************************************************************************/ | ||
2495 | IMG_EXPORT | ||
2496 | PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM) | ||
2497 | { | ||
2498 | PVRSRV_ERROR eError; | ||
2499 | PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; | ||
2500 | |||
2501 | psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM; | ||
2502 | |||
2503 | /* Remove the item from the resman list and trigger the callback. */ | ||
2504 | eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem, CLEANUP_WITH_POLL); | ||
2505 | |||
2506 | return eError; | ||
2507 | } | ||
2508 | |||
2509 | |||
2510 | static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam, | ||
2511 | IMG_UINT32 ui32Param, | ||
2512 | IMG_BOOL bDummy) | ||
2513 | { | ||
2514 | PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; | ||
2515 | PVRSRV_BUFFERCLASS_INFO *psBCInfo; | ||
2516 | IMG_UINT32 i; | ||
2517 | |||
2518 | PVR_UNREFERENCED_PARAMETER(ui32Param); | ||
2519 | PVR_UNREFERENCED_PARAMETER(bDummy); | ||
2520 | |||
2521 | psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)pvParam; | ||
2522 | |||
2523 | psBCInfo = psBCPerContextInfo->psBCInfo; | ||
2524 | |||
2525 | for (i = 0; i < psBCInfo->ui32BufferCount; i++) | ||
2526 | { | ||
2527 | if (psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount != 0) | ||
2528 | { | ||
2529 | PVR_DPF((PVR_DBG_ERROR, "CloseBCDeviceCallBack: buffer %d (0x%p) still mapped (ui32MemMapRefCount = %d)", | ||
2530 | i, | ||
2531 | &psBCInfo->psBuffer[i].sDeviceClassBuffer, | ||
2532 | psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount)); | ||
2533 | return PVRSRV_ERROR_STILL_MAPPED; | ||
2534 | } | ||
2535 | } | ||
2536 | |||
2537 | psBCInfo->ui32RefCount--; | ||
2538 | if(psBCInfo->ui32RefCount == 0) | ||
2539 | { | ||
2540 | /* close the external device */ | ||
2541 | psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice); | ||
2542 | |||
2543 | /* free syncinfos */ | ||
2544 | for(i=0; i<psBCInfo->ui32BufferCount; i++) | ||
2545 | { | ||
2546 | if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) | ||
2547 | { | ||
2548 | PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); | ||
2549 | } | ||
2550 | } | ||
2551 | |||
2552 | /* free buffers */ | ||
2553 | if(psBCInfo->psBuffer) | ||
2554 | { | ||
2555 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL); | ||
2556 | psBCInfo->psBuffer = IMG_NULL; | ||
2557 | } | ||
2558 | } | ||
2559 | |||
2560 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL); | ||
2561 | /*not nulling pointer, copy on stack*/ | ||
2562 | |||
2563 | return PVRSRV_OK; | ||
2564 | } | ||
2565 | |||
2566 | |||
2567 | /*! | ||
2568 | ****************************************************************************** | ||
2569 | |||
2570 | @Function PVRSRVOpenBCDeviceKM | ||
2571 | |||
2572 | @Description | ||
2573 | |||
2574 | Opens a connection to the Buffer Class device, associating the connection | ||
2575 | with a Device Memory Context for a services managed device | ||
2576 | |||
2577 | @Input psPerProc : Per-process data | ||
2578 | @Input ui32DeviceID : unique device index | ||
2579 | @Input hDevCookie : devcookie used to derive the Device Memory | ||
2580 | Context into BC surfaces will be mapped into | ||
2581 | @Outut phDeviceKM : handle to the DC device | ||
2582 | |||
2583 | @Return PVRSRV_ERROR : | ||
2584 | |||
2585 | ******************************************************************************/ | ||
2586 | IMG_EXPORT | ||
2587 | PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc, | ||
2588 | IMG_UINT32 ui32DeviceID, | ||
2589 | IMG_HANDLE hDevCookie, | ||
2590 | IMG_HANDLE *phDeviceKM) | ||
2591 | { | ||
2592 | PVRSRV_BUFFERCLASS_INFO *psBCInfo; | ||
2593 | PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo; | ||
2594 | PVRSRV_DEVICE_NODE *psDeviceNode; | ||
2595 | SYS_DATA *psSysData; | ||
2596 | IMG_UINT32 i; | ||
2597 | PVRSRV_ERROR eError; | ||
2598 | |||
2599 | if(!phDeviceKM || !hDevCookie) | ||
2600 | { | ||
2601 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Invalid params")); | ||
2602 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
2603 | } | ||
2604 | |||
2605 | SysAcquireData(&psSysData); | ||
2606 | |||
2607 | /* find the matching devicenode */ | ||
2608 | psDeviceNode = (PVRSRV_DEVICE_NODE*) | ||
2609 | List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList, | ||
2610 | &MatchDeviceKM_AnyVaCb, | ||
2611 | ui32DeviceID, | ||
2612 | IMG_FALSE, | ||
2613 | PVRSRV_DEVICE_CLASS_BUFFER); | ||
2614 | if (!psDeviceNode) | ||
2615 | { | ||
2616 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: No devnode matching index %d", ui32DeviceID)); | ||
2617 | return PVRSRV_ERROR_NO_DEVICENODE_FOUND; | ||
2618 | } | ||
2619 | psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice; | ||
2620 | |||
2621 | /* | ||
2622 | FoundDevice: | ||
2623 | */ | ||
2624 | /* | ||
2625 | Allocate the per-context BC Info before calling the external device, | ||
2626 | to make error handling easier. | ||
2627 | */ | ||
2628 | if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
2629 | sizeof(*psBCPerContextInfo), | ||
2630 | (IMG_VOID **)&psBCPerContextInfo, IMG_NULL, | ||
2631 | "Buffer Class per Context Info") != PVRSRV_OK) | ||
2632 | { | ||
2633 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed psBCPerContextInfo alloc")); | ||
2634 | return PVRSRV_ERROR_OUT_OF_MEMORY; | ||
2635 | } | ||
2636 | OSMemSet(psBCPerContextInfo, 0, sizeof(*psBCPerContextInfo)); | ||
2637 | |||
2638 | if(psBCInfo->ui32RefCount++ == 0) | ||
2639 | { | ||
2640 | BUFFER_INFO sBufferInfo; | ||
2641 | |||
2642 | psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie; | ||
2643 | |||
2644 | /* store the device kernel context to map into */ | ||
2645 | psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext; | ||
2646 | |||
2647 | /* open the external device */ | ||
2648 | eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice); | ||
2649 | if(eError != PVRSRV_OK) | ||
2650 | { | ||
2651 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to open external BC device")); | ||
2652 | return eError; | ||
2653 | } | ||
2654 | |||
2655 | /* get information about the buffers */ | ||
2656 | eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo); | ||
2657 | if(eError != PVRSRV_OK) | ||
2658 | { | ||
2659 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM : Failed to get BC Info")); | ||
2660 | return eError; | ||
2661 | } | ||
2662 | |||
2663 | /* interpret and store info */ | ||
2664 | psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount; | ||
2665 | |||
2666 | /* allocate BC buffers */ | ||
2667 | eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, | ||
2668 | sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount, | ||
2669 | (IMG_VOID **)&psBCInfo->psBuffer, | ||
2670 | IMG_NULL, | ||
2671 | "Array of Buffer Class Buffer"); | ||
2672 | if(eError != PVRSRV_OK) | ||
2673 | { | ||
2674 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to allocate BC buffers")); | ||
2675 | return eError; | ||
2676 | } | ||
2677 | OSMemSet (psBCInfo->psBuffer, | ||
2678 | 0, | ||
2679 | sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount); | ||
2680 | |||
2681 | for(i=0; i<psBCInfo->ui32BufferCount; i++) | ||
2682 | { | ||
2683 | /* create a syncinfo for the device's system surface */ | ||
2684 | eError = PVRSRVAllocSyncInfoKM(IMG_NULL, | ||
2685 | psBCInfo->hDevMemContext, | ||
2686 | &psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo); | ||
2687 | if(eError != PVRSRV_OK) | ||
2688 | { | ||
2689 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc")); | ||
2690 | goto ErrorExit; | ||
2691 | } | ||
2692 | |||
2693 | /* | ||
2694 | get the buffers from the buffer class | ||
2695 | drivers by index, passing-in the syncdata objects | ||
2696 | */ | ||
2697 | eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice, | ||
2698 | i, | ||
2699 | psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData, | ||
2700 | &psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtBuffer); | ||
2701 | if(eError != PVRSRV_OK) | ||
2702 | { | ||
2703 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed to get BC buffers")); | ||
2704 | goto ErrorExit; | ||
2705 | } | ||
2706 | |||
2707 | /* setup common device class info */ | ||
2708 | psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr; | ||
2709 | psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext; | ||
2710 | psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice; | ||
2711 | psBCInfo->psBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount = 0; | ||
2712 | } | ||
2713 | } | ||
2714 | |||
2715 | psBCPerContextInfo->psBCInfo = psBCInfo; | ||
2716 | psBCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext, | ||
2717 | RESMAN_TYPE_BUFFERCLASS_DEVICE, | ||
2718 | psBCPerContextInfo, | ||
2719 | 0, | ||
2720 | &CloseBCDeviceCallBack); | ||
2721 | |||
2722 | /* return a reference to the BCPerContextInfo */ | ||
2723 | *phDeviceKM = (IMG_HANDLE)psBCPerContextInfo; | ||
2724 | |||
2725 | return PVRSRV_OK; | ||
2726 | |||
2727 | ErrorExit: | ||
2728 | |||
2729 | /* free syncinfos */ | ||
2730 | for(i=0; i<psBCInfo->ui32BufferCount; i++) | ||
2731 | { | ||
2732 | if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo) | ||
2733 | { | ||
2734 | PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL); | ||
2735 | } | ||
2736 | } | ||
2737 | |||
2738 | /* free buffers */ | ||
2739 | if(psBCInfo->psBuffer) | ||
2740 | { | ||
2741 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL); | ||
2742 | psBCInfo->psBuffer = IMG_NULL; | ||
2743 | } | ||
2744 | |||
2745 | return eError; | ||
2746 | } | ||
2747 | |||
2748 | |||
2749 | |||
2750 | |||
2751 | /****************************************************************************** | ||
2752 | |||
2753 | @Function PVRSRVGetBCInfoKM | ||
2754 | |||
2755 | @Description | ||
2756 | |||
2757 | Gets Buffer Class device Info | ||
2758 | |||
2759 | @Input hDeviceKM : device handle | ||
2760 | @Output psBufferInfo | ||
2761 | |||
2762 | @Return PVRSRV_ERROR : | ||
2763 | |||
2764 | ******************************************************************************/ | ||
2765 | IMG_EXPORT | ||
2766 | PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM, | ||
2767 | BUFFER_INFO *psBufferInfo) | ||
2768 | { | ||
2769 | PVRSRV_BUFFERCLASS_INFO *psBCInfo; | ||
2770 | PVRSRV_ERROR eError; | ||
2771 | |||
2772 | if(!hDeviceKM || !psBufferInfo) | ||
2773 | { | ||
2774 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM: Invalid parameters")); | ||
2775 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
2776 | } | ||
2777 | |||
2778 | psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM); | ||
2779 | |||
2780 | eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, psBufferInfo); | ||
2781 | |||
2782 | if(eError != PVRSRV_OK) | ||
2783 | { | ||
2784 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCInfoKM : Failed to get BC Info")); | ||
2785 | return eError; | ||
2786 | } | ||
2787 | |||
2788 | return PVRSRV_OK; | ||
2789 | } | ||
2790 | |||
2791 | |||
2792 | /****************************************************************************** | ||
2793 | |||
2794 | @Function PVRSRVGetBCBufferKM | ||
2795 | |||
2796 | @Description | ||
2797 | |||
2798 | Gets Buffer Class Buffer Handle | ||
2799 | |||
2800 | @Input hDeviceKM : device handle | ||
2801 | @Output psBufferInfo | ||
2802 | |||
2803 | @Return PVRSRV_ERROR : | ||
2804 | |||
2805 | ******************************************************************************/ | ||
2806 | IMG_EXPORT | ||
2807 | PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM, | ||
2808 | IMG_UINT32 ui32BufferIndex, | ||
2809 | IMG_HANDLE *phBuffer) | ||
2810 | { | ||
2811 | PVRSRV_BUFFERCLASS_INFO *psBCInfo; | ||
2812 | |||
2813 | if(!hDeviceKM || !phBuffer) | ||
2814 | { | ||
2815 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Invalid parameters")); | ||
2816 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
2817 | } | ||
2818 | |||
2819 | psBCInfo = BCDeviceHandleToBCInfo(hDeviceKM); | ||
2820 | |||
2821 | if(ui32BufferIndex < psBCInfo->ui32BufferCount) | ||
2822 | { | ||
2823 | *phBuffer = (IMG_HANDLE)&psBCInfo->psBuffer[ui32BufferIndex]; | ||
2824 | } | ||
2825 | else | ||
2826 | { | ||
2827 | PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetBCBufferKM: Buffer index %d out of range (%d)", ui32BufferIndex,psBCInfo->ui32BufferCount)); | ||
2828 | return PVRSRV_ERROR_INVALID_PARAMS; | ||
2829 | } | ||
2830 | |||
2831 | return PVRSRV_OK; | ||
2832 | } | ||
2833 | |||
2834 | |||
2835 | /*! | ||
2836 | ****************************************************************************** | ||
2837 | |||
2838 | @Function PVRGetBufferClassJTable | ||
2839 | |||
2840 | @Description | ||
2841 | |||
2842 | Sets up function table for 3rd party Buffer Class Device to call through | ||
2843 | |||
2844 | @Input psJTable : pointer to function pointer table memory | ||
2845 | |||
2846 | @Return PVRSRV_ERROR : | ||
2847 | |||
2848 | ******************************************************************************/ | ||
2849 | IMG_EXPORT | ||
2850 | IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable) | ||
2851 | { | ||
2852 | psJTable->ui32TableSize = sizeof(PVRSRV_BC_BUFFER2SRV_KMJTABLE); | ||
2853 | |||
2854 | psJTable->pfnPVRSRVRegisterBCDevice = &PVRSRVRegisterBCDeviceKM; | ||
2855 | psJTable->pfnPVRSRVScheduleDevices = &PVRSRVScheduleDevicesKM; | ||
2856 | psJTable->pfnPVRSRVRemoveBCDevice = &PVRSRVRemoveBCDeviceKM; | ||
2857 | |||
2858 | return IMG_TRUE; | ||
2859 | } | ||
2860 | |||
2861 | /****************************************************************************** | ||
2862 | End of file (deviceclass.c) | ||
2863 | ******************************************************************************/ | ||