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::Dimension& 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(const char* pName)
216 SysTryReturnVoidResult(NID_SHELL, pName, E_INVALID_ARG, "[E_INVALID_ARG] The argument is invalid.");
217 SysTryReturnVoidResult(NID_SHELL, __pBuffer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
219 return __pBuffer->Dump(pName);
222 _AppWidgetBuffer::_Buffer::_Buffer(_AppWidgetBuffer* pAppWidgetBuffer)
225 , __depth(sizeof(int))
226 , __pAppWidgetBuffer(pAppWidgetBuffer)
231 __xShmSegmentInfo.shmseg = 0;
232 __xShmSegmentInfo.shmid = -1;
233 __xShmSegmentInfo.shmaddr = 0;
234 __xShmSegmentInfo.readOnly = False;
237 _AppWidgetBuffer::_Buffer::~_Buffer(void)
243 _AppWidgetBuffer::_Buffer::AllocBuffer(Pixmap pixmap, const Tizen::Graphics::Dimension& size)
254 _AppWidgetBuffer::_Buffer::DeallocBuffer(void)
260 _AppWidgetBuffer::_Buffer::LockBuffer(void)
264 return OnLockBuffer();
268 _AppWidgetBuffer::_Buffer::UnlockBuffer(void)
272 return OnUnlockBuffer();
276 _AppWidgetBuffer::_Buffer::GetGc(void) const
282 _AppWidgetBuffer::_Buffer::GetXImage(void) const
288 _AppWidgetBuffer::_Buffer::GetPixmap(void) const
294 _AppWidgetBuffer::_Buffer::Dump(const char* pName)
296 void* pBuffer = null;
300 pBuffer = GetBuffer();
305 pBuffer = LockBuffer();
308 SysTryReturnVoidResult(NID_SHELL, pBuffer, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
310 int size = __size.width * __size.height * __depth;
313 memset(fileName, 0, sizeof(fileName));
314 snprintf(fileName, sizeof(fileName), "./dump-%s-%d.raw", pName, __dumpFileIndex++);
316 FILE* pFile = fopen(fileName, "w+b");
319 fwrite(pBuffer, size, 1, pFile);
321 SysSecureLog(NID_SHELL, "buffer (0x%x) size (%d) pixmapId (%d)", pBuffer, size, __pixmap);
325 SysSecureLog(NID_SHELL, "File open failed: (%s) buffer (0x%x) size (%d) pixmapId (%d)", strerror(errno), pBuffer, size, __pixmap);
335 _AppWidgetBuffer::_Buffer::GetBuffer(void)
337 return OnLockBuffer();
341 _AppWidgetBuffer::_Buffer::DeleteBuffer(void)
343 if (__pAppWidgetBuffer->__pDisplay.get())
347 XFreeGC(__pAppWidgetBuffer->__pDisplay.get(), __gc);
348 XShmDetach(__pAppWidgetBuffer->__pDisplay.get(), &__xShmSegmentInfo);
352 XDestroyImage(__pXImage);
356 if (__xShmSegmentInfo.shmaddr)
358 shmdt(__xShmSegmentInfo.shmaddr);
359 __xShmSegmentInfo.shmaddr = null;
362 if (__xShmSegmentInfo.shmid >= 0)
364 shmctl(__xShmSegmentInfo.shmid, IPC_RMID, 0);
365 __xShmSegmentInfo.shmid = -1;
374 _AppWidgetBuffer::_Buffer::OnCreateBuffer(void)
376 int bufferSize = __size.width * __size.height * __depth;
377 SysLog(NID_SHELL, "%d [%d %d %d]", bufferSize, __size.width, __size.height, __depth);
379 __xShmSegmentInfo.shmid = shmget(IPC_PRIVATE, bufferSize, IPC_CREAT | 0666);
380 SysTryReturnVoidResult(NID_SHELL, __xShmSegmentInfo.shmid >= 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
382 __xShmSegmentInfo.readOnly = False;
383 __xShmSegmentInfo.shmaddr = static_cast<char*>(shmat(__xShmSegmentInfo.shmid, null, 0));
384 SysTryCatch(NID_SHELL, __xShmSegmentInfo.shmaddr != (void*)-1, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
386 __pXImage = XShmCreateImage(__pAppWidgetBuffer->__pDisplay.get(), __pAppWidgetBuffer->__pVisual, 32, ZPixmap, null, &__xShmSegmentInfo, __size.width, __size.height);
387 SysTryCatch(NID_SHELL, __pXImage, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
389 __pXImage->data = __xShmSegmentInfo.shmaddr;
390 XShmAttach(__pAppWidgetBuffer->__pDisplay.get(), &__xShmSegmentInfo);
391 XSync(__pAppWidgetBuffer->__pDisplay.get(), False);
393 __gc = XCreateGC(__pAppWidgetBuffer->__pDisplay.get(), static_cast<Pixmap>(__pixmap), 0, null);
394 SysTryCatch(NID_SHELL, __gc, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
400 XShmDetach(__pAppWidgetBuffer->__pDisplay.get(), &__xShmSegmentInfo);
404 XDestroyImage(__pXImage);
408 if (__xShmSegmentInfo.shmaddr != (void *)-1)
410 shmdt(__xShmSegmentInfo.shmaddr);
411 __xShmSegmentInfo.shmaddr = null;
414 if (__xShmSegmentInfo.shmid >= 0)
416 shmctl(__xShmSegmentInfo.shmid, IPC_RMID, 0);
417 __xShmSegmentInfo.shmid = -1;
422 _AppWidgetBuffer::_Buffer::OnDeleteBuffer(void)
428 _AppWidgetBuffer::_Buffer::OnLockBuffer(void)
430 return __xShmSegmentInfo.shmaddr;
434 _AppWidgetBuffer::_Buffer::OnUnlockBuffer(void)
440 _AppWidgetBuffer::_Buffer::OnGetBuffer(void)
442 return __xShmSegmentInfo.shmaddr;
445 _AppWidgetBuffer::_GemBuffer::_GemBuffer(_AppWidgetBuffer* pAppWidgetBuffer)
446 : _Buffer(pAppWidgetBuffer)
447 , __pDri2Buffer(null)
452 , __pCompensateBuffer(null)
454 __attachments[0] = DRI2BufferFrontLeft;
457 _AppWidgetBuffer::_GemBuffer::~_GemBuffer(void)
463 _AppWidgetBuffer::_GemBuffer::DeleteGemBuffer(void)
465 if (__pCompensateBuffer)
467 free(__pCompensateBuffer);
468 __pCompensateBuffer = null;
473 tbm_bo_unref(__pTbmBo);
476 DRI2DestroyDrawable(__pAppWidgetBuffer->__pDisplay.get(), __pixmap);
481 _AppWidgetBuffer::_GemBuffer::OnCreateBuffer(void)
483 SysLog(NID_SHELL, "[%d %d]", __size.width, __size.height);
485 unsigned int pitch = 0;
487 DRI2CreateDrawable(__pAppWidgetBuffer->__pDisplay.get(), __pixmap);
489 int width = __size.width;
490 int height = __size.height;
492 __pDri2Buffer = DRI2GetBuffers(__pAppWidgetBuffer->__pDisplay.get(), __pixmap, &width, &height, __attachments, __count, &__outCount);
493 SysTryCatch(NID_SHELL, __pDri2Buffer && __pDri2Buffer->name, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
495 __gemSize.width = width;
496 __gemSize.height = height;
498 SysSecureLog(NID_SHELL, "0x%x [%d %d %d] [%d %d]", __pDri2Buffer, __outCount, __pDri2Buffer->name, __pDri2Buffer->pitch, width, height);
500 __pTbmBo = tbm_bo_import(__pAppWidgetBuffer->__pBufMgr.get(), __pDri2Buffer->name);
501 SysTryCatch(NID_SHELL, __pTbmBo, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
503 pitch = __gemSize.width * __depth;
504 if (__pDri2Buffer->pitch != pitch)
506 __pCompensateBuffer = calloc(1, pitch * __gemSize.height);
507 SysTryCatch(NID_SHELL, __pCompensateBuffer, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory is insufficient.");
509 SysLog(NID_SHELL, "0x%x [%d %d %d]", __pCompensateBuffer, __depth, __gemSize.width, __gemSize.height);
516 DRI2DestroyDrawable(__pAppWidgetBuffer->__pDisplay.get(), __pixmap);
520 _AppWidgetBuffer::_GemBuffer::OnDeleteBuffer(void)
526 _AppWidgetBuffer::_GemBuffer::OnLockBuffer(void)
530 tbm_bo_handle handle;
531 handle = tbm_bo_map(__pTbmBo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
532 __pGemBuffer = handle.ptr;
535 return __pCompensateBuffer ? __pCompensateBuffer : __pGemBuffer;
539 _AppWidgetBuffer::_GemBuffer::OnUnlockBuffer(void)
543 if (__pCompensateBuffer)
545 int* pPixel = (int*)__pCompensateBuffer;
546 int* pGemPixel = (int*)__pGemBuffer;
547 int gap = __pDri2Buffer->pitch - (__gemSize.width * __depth);
549 for (int y = 0; y < __gemSize.height; y++)
551 for (int x = 0; x < __gemSize.width; x++)
553 *pGemPixel++ = *pPixel++;
556 pGemPixel = (int*)(((char*)pGemPixel) + gap);
560 tbm_bo_unmap(__pTbmBo);
566 _AppWidgetBuffer::_GemBuffer::OnGetBuffer(void)