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