2 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.1 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://floralicense.org/license/
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 * @file FShell_AppWidgetBuffer.cpp
18 * @brief This is the implementation file for the _AppWidgetBuffer class.
29 #include <sys/types.h>
34 #include <FBaseSysLog.h>
35 #include "FShell_AppWidgetBuffer.h"
38 using namespace Tizen::Base;
39 using namespace Tizen::Graphics;
41 namespace Tizen { namespace Shell
44 _AppWidgetBuffer::_AppWidgetBuffer(void)
47 , __dri2FileDescriptor(-1)
51 _AppWidgetBuffer::~_AppWidgetBuffer(void)
57 void operator()(char* pStr)
64 _AppWidgetBuffer::Initialize(void)
66 __pDisplay.reset(XOpenDisplay(null));
67 SysTryReturnVoidResult(NID_SHELL, __pDisplay, E_SYSTEM, "[E_SYSTEM] Propagating.");
69 Screen* pScreen = DefaultScreenOfDisplay(__pDisplay.get());
70 __screen = DefaultScreen(__pDisplay.get());
71 __pVisual = DefaultVisualOfScreen(pScreen);
72 SysTryReturnVoidResult(NID_SHELL, __pVisual, E_SYSTEM, "[E_SYSTEM] Propagating.");
77 ret = DRI2QueryExtension(__pDisplay.get(), &eventBase, &errorBase);
80 SysLog(NID_SHELL, "Do not support");
86 ret = DRI2QueryVersion(__pDisplay.get(), &dri2Major, &dri2Minor);
89 SysLog(NID_SHELL, "Do not support");
93 char* pDriverNameTemp = null;
94 char* pDeviceNameTemp = null;
96 ret = DRI2Connect(__pDisplay.get(), DefaultRootWindow(__pDisplay.get()), &pDriverNameTemp, &pDeviceNameTemp);
99 SysLog(NID_SHELL, "Do not support");
103 unique_ptr<char, _Deleter> pDriverName(pDriverNameTemp);
104 unique_ptr<char, _Deleter> pDeviceName(pDeviceNameTemp);
106 unique_ptr<int, _FileDescriptorDeleter> fileDescriptor(open(pDeviceName.get(), O_RDWR));
107 if (fileDescriptor.get() < 0)
109 SysLog(NID_SHELL, "Do not support");
113 drm_magic_t magic = 0;
114 drmGetMagic(fileDescriptor.get(), &magic);
115 SysLog(NID_SHELL, "Magic [0x%x]", magic);
116 ret = DRI2Authenticate(__pDisplay.get(), DefaultRootWindow(__pDisplay.get()), magic);
117 SysTryReturnVoidResult(NID_SHELL, ret == True, E_SYSTEM, "[E_SYSTEM] Propagating.");
119 unique_ptr<tbm_bufmgr, _TbmBufMgrDeleter> pBufMgr(tbm_bufmgr_init(fileDescriptor.get()));
120 SysTryReturnVoidResult(NID_SHELL, pBufMgr, E_SYSTEM, "[E_SYSTEM] Propagating.");
122 __dri2FileDescriptor = move(fileDescriptor);
123 __pBufMgr = move(pBufMgr);
127 _AppWidgetBuffer::AllocBuffer(Pixmap pixmap, const Tizen::Graphics::FloatDimension& size)
129 unique_ptr<_Buffer> pBuffer;
131 if (!IsGemBufferEnabled())
133 pBuffer.reset(new (std::nothrow) _Buffer(this));
137 pBuffer.reset(new (std::nothrow) _GemBuffer(this));
140 SysTryReturn(NID_SHELL, pBuffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
142 void* pNativeBuffer = pBuffer->AllocBuffer(pixmap, size);
143 SysTryReturn(NID_SHELL, pNativeBuffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
145 __pBuffer = move(pBuffer);
147 return pNativeBuffer;
151 _AppWidgetBuffer::DeallocBuffer(void)
153 SysTryReturnVoidResult(NID_SHELL, __pBuffer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
155 __pBuffer->DeallocBuffer();
159 _AppWidgetBuffer::LockBuffer(void)
161 SysTryReturn(NID_SHELL, __pBuffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
163 void* pNativeBuffer = __pBuffer->LockBuffer();
164 SysTryReturn(NID_SHELL, pNativeBuffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
166 return pNativeBuffer;
170 _AppWidgetBuffer::UnlockBuffer(void)
172 SysTryReturnVoidResult(NID_SHELL, __pBuffer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
174 __pBuffer->UnlockBuffer();
178 _AppWidgetBuffer::IsGemBufferEnabled(void) const
180 return (__dri2FileDescriptor.get() >= 0);
184 _AppWidgetBuffer::GetDisplay(void) const
186 return __pDisplay.get();
190 _AppWidgetBuffer::GetGc(void) const
192 SysTryReturn(NID_SHELL, __pBuffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
194 return __pBuffer->GetGc();
198 _AppWidgetBuffer::GetXImage(void) const
200 SysTryReturn(NID_SHELL, __pBuffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
202 return __pBuffer->GetXImage();
206 _AppWidgetBuffer::GetPixmap(void) const
208 SysTryReturn(NID_SHELL, __pBuffer, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
210 return __pBuffer->GetPixmap();
214 _AppWidgetBuffer::Dump(void)
216 SysTryReturnVoidResult(NID_SHELL, __pBuffer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
218 return __pBuffer->Dump();
221 _AppWidgetBuffer::_Buffer::_Buffer(_AppWidgetBuffer* pAppWidgetBuffer)
224 , __depth(sizeof(int))
225 , __pAppWidgetBuffer(pAppWidgetBuffer)
230 __xShmSegmentInfo.shmseg = 0;
231 __xShmSegmentInfo.shmid = -1;
232 __xShmSegmentInfo.shmaddr = 0;
233 __xShmSegmentInfo.readOnly = False;
236 _AppWidgetBuffer::_Buffer::~_Buffer(void)
242 _AppWidgetBuffer::_Buffer::AllocBuffer(Pixmap pixmap, const Tizen::Graphics::FloatDimension& size)
253 _AppWidgetBuffer::_Buffer::DeallocBuffer(void)
259 _AppWidgetBuffer::_Buffer::LockBuffer(void)
263 return OnLockBuffer();
267 _AppWidgetBuffer::_Buffer::UnlockBuffer(void)
271 return OnUnlockBuffer();
275 _AppWidgetBuffer::_Buffer::GetGc(void) const
281 _AppWidgetBuffer::_Buffer::GetXImage(void) const
287 _AppWidgetBuffer::_Buffer::GetPixmap(void) const
293 _AppWidgetBuffer::_Buffer::Dump(void)
295 void* pBuffer = null;
299 pBuffer = GetBuffer();
304 pBuffer = LockBuffer();
307 SysTryReturnVoidResult(NID_SHELL, pBuffer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
309 int size = static_cast<int>(__size.width) * static_cast<int>(__size.height) * __depth;
312 memset(fileName, 0, sizeof(fileName));
313 snprintf(fileName, sizeof(fileName), "./dump%d.raw", __dumpFileIndex++);
315 FILE* pFile = fopen(fileName, "w+b");
318 fwrite(pBuffer, size, 1, pFile);
320 SysSecureLog(NID_SHELL, "buffer (0x%x) size (%d) pixmapId (%d)", pBuffer, size, __pixmap);
324 SysSecureLog(NID_SHELL, "File open failed: (%s) buffer (0x%x) size (%d) pixmapId (%d)", strerror(errno), pBuffer, size, __pixmap);
334 _AppWidgetBuffer::_Buffer::GetBuffer(void)
336 return OnLockBuffer();
340 _AppWidgetBuffer::_Buffer::DeleteBuffer(void)
342 if (__pAppWidgetBuffer->__pDisplay.get())
346 XFreeGC(__pAppWidgetBuffer->__pDisplay.get(), __gc);
347 XShmDetach(__pAppWidgetBuffer->__pDisplay.get(), &__xShmSegmentInfo);
351 XDestroyImage(__pXImage);
355 if (__xShmSegmentInfo.shmaddr)
357 shmdt(__xShmSegmentInfo.shmaddr);
358 __xShmSegmentInfo.shmaddr = null;
361 if (__xShmSegmentInfo.shmid >= 0)
363 shmctl(__xShmSegmentInfo.shmid, IPC_RMID, 0);
364 __xShmSegmentInfo.shmid = -1;
373 _AppWidgetBuffer::_Buffer::OnCreateBuffer(void)
375 int bufferSize = static_cast<int>(__size.width) * static_cast<int>(__size.height) * __depth;
376 SysLog(NID_SHELL, "%d [%f %f %d]", bufferSize, __size.width, __size.height, __depth);
378 __xShmSegmentInfo.shmid = shmget(IPC_PRIVATE, bufferSize, IPC_CREAT | 0666);
379 SysTryReturnVoidResult(NID_SHELL, __xShmSegmentInfo.shmid >= 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
381 __xShmSegmentInfo.readOnly = False;
382 __xShmSegmentInfo.shmaddr = static_cast<char*>(shmat(__xShmSegmentInfo.shmid, null, 0));
383 SysTryCatch(NID_SHELL, __xShmSegmentInfo.shmaddr != (void*)-1, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
385 __pXImage = XShmCreateImage(__pAppWidgetBuffer->__pDisplay.get(), __pAppWidgetBuffer->__pVisual, 32, ZPixmap, null, &__xShmSegmentInfo, __size.width, __size.height);
386 SysTryCatch(NID_SHELL, __pXImage, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
388 __pXImage->data = __xShmSegmentInfo.shmaddr;
389 XShmAttach(__pAppWidgetBuffer->__pDisplay.get(), &__xShmSegmentInfo);
390 XSync(__pAppWidgetBuffer->__pDisplay.get(), False);
392 __gc = XCreateGC(__pAppWidgetBuffer->__pDisplay.get(), static_cast<Pixmap>(__pixmap), 0, null);
393 SysTryCatch(NID_SHELL, __gc, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
399 XShmDetach(__pAppWidgetBuffer->__pDisplay.get(), &__xShmSegmentInfo);
403 XDestroyImage(__pXImage);
407 if (__xShmSegmentInfo.shmaddr != (void *)-1)
409 shmdt(__xShmSegmentInfo.shmaddr);
410 __xShmSegmentInfo.shmaddr = null;
413 if (__xShmSegmentInfo.shmid >= 0)
415 shmctl(__xShmSegmentInfo.shmid, IPC_RMID, 0);
416 __xShmSegmentInfo.shmid = -1;
421 _AppWidgetBuffer::_Buffer::OnDeleteBuffer(void)
427 _AppWidgetBuffer::_Buffer::OnLockBuffer(void)
429 return __xShmSegmentInfo.shmaddr;
433 _AppWidgetBuffer::_Buffer::OnUnlockBuffer(void)
439 _AppWidgetBuffer::_Buffer::OnGetBuffer(void)
441 return __xShmSegmentInfo.shmaddr;
444 _AppWidgetBuffer::_GemBuffer::_GemBuffer(_AppWidgetBuffer* pAppWidgetBuffer)
445 : _Buffer(pAppWidgetBuffer)
446 , __pDri2Buffer(null)
451 , __pCompensateBuffer(null)
453 __attachments[0] = DRI2BufferFrontLeft;
456 _AppWidgetBuffer::_GemBuffer::~_GemBuffer(void)
462 _AppWidgetBuffer::_GemBuffer::DeleteGemBuffer(void)
464 if (__pCompensateBuffer)
466 free(__pCompensateBuffer);
467 __pCompensateBuffer = null;
472 tbm_bo_unref(__pTbmBo);
475 DRI2DestroyDrawable(__pAppWidgetBuffer->__pDisplay.get(), __pixmap);
480 _AppWidgetBuffer::_GemBuffer::OnCreateBuffer(void)
482 SysLog(NID_SHELL, "[%f %f]", __size.width, __size.height);
484 unsigned int pitch = 0;
486 DRI2CreateDrawable(__pAppWidgetBuffer->__pDisplay.get(), __pixmap);
488 int width = static_cast<int>(__size.width);
489 int height = static_cast<int>(__size.height);
491 __pDri2Buffer = DRI2GetBuffers(__pAppWidgetBuffer->__pDisplay.get(), __pixmap, &width, &height, __attachments, __count, &__outCount);
492 SysTryCatch(NID_SHELL, __pDri2Buffer && __pDri2Buffer->name, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
494 __gemSize.width = width;
495 __gemSize.height = height;
497 SysSecureLog(NID_SHELL, "0x%x [%d %d %d] [%d %d]", __pDri2Buffer, __outCount, __pDri2Buffer->name, __pDri2Buffer->pitch, width, height);
499 __pTbmBo = tbm_bo_import(__pAppWidgetBuffer->__pBufMgr.get(), __pDri2Buffer->name);
500 SysTryCatch(NID_SHELL, __pTbmBo, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
502 pitch = __gemSize.width * __depth;
503 if (__pDri2Buffer->pitch != pitch)
505 __pCompensateBuffer = calloc(1, pitch * __gemSize.height);
506 SysTryCatch(NID_SHELL, __pCompensateBuffer, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
508 SysLog(NID_SHELL, "0x%x [%d %d %d]", __pCompensateBuffer, __depth, __gemSize.width, __gemSize.height);
515 DRI2DestroyDrawable(__pAppWidgetBuffer->__pDisplay.get(), __pixmap);
519 _AppWidgetBuffer::_GemBuffer::OnDeleteBuffer(void)
525 _AppWidgetBuffer::_GemBuffer::OnLockBuffer(void)
529 tbm_bo_handle handle;
530 handle = tbm_bo_map(__pTbmBo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
531 __pGemBuffer = handle.ptr;
534 return __pCompensateBuffer ? __pCompensateBuffer : __pGemBuffer;
538 _AppWidgetBuffer::_GemBuffer::OnUnlockBuffer(void)
542 if (__pCompensateBuffer)
544 int* pPixel = (int*)__pCompensateBuffer;
545 int* pGemPixel = (int*)__pGemBuffer;
546 int gap = __pDri2Buffer->pitch - (__gemSize.width * __depth);
548 for (int y = 0; y < __gemSize.height; y++)
550 for (int x = 0; x < __gemSize.width; x++)
552 *pGemPixel++ = *pPixel++;
555 pGemPixel = (int*)(((char*)pGemPixel) + gap);
559 tbm_bo_unmap(__pTbmBo);
565 _AppWidgetBuffer::_GemBuffer::OnGetBuffer(void)