00001
00002 #include "config.h"
00003
00004
00005 #include <QCoreApplication>
00006 #include <QPainter>
00007 #include <QMutex>
00008 #include <QX11Info>
00009
00010
00011 #include "mythlogging.h"
00012
00013
00014 #include "mythrender_vdpau.h"
00015
00016
00017 #include "mythpainter_vdpau.h"
00018
00019 #define LOC QString("VDPAU Painter: ")
00020
00021 MythVDPAUPainter::MythVDPAUPainter(MythRenderVDPAU *render) :
00022 MythPainter(), m_render(render), m_created_render(true), m_target(0),
00023 m_swap_control(true)
00024 {
00025 if (m_render)
00026 m_created_render = false;
00027 }
00028
00029 MythVDPAUPainter::~MythVDPAUPainter()
00030 {
00031 Teardown();
00032 }
00033
00034 bool MythVDPAUPainter::InitVDPAU(QPaintDevice *parent)
00035 {
00036 if (m_render)
00037 return true;
00038
00039 QWidget *real_parent = (QWidget*)parent;
00040 if (!real_parent)
00041 return false;
00042
00043 m_render = new MythRenderVDPAU();
00044 if (!m_render)
00045 return false;
00046
00047 m_created_render = true;
00048 if (m_render->Create(real_parent->size(), real_parent->winId()))
00049 return true;
00050
00051 Teardown();
00052 return false;
00053 }
00054
00055 void MythVDPAUPainter::Teardown(void)
00056 {
00057 ExpireImages();
00058 FreeResources();
00059
00060 m_ImageBitmapMap.clear();
00061 m_ImageExpireList.clear();
00062 m_bitmapDeleteList.clear();
00063
00064 if (m_render)
00065 {
00066 if (m_created_render)
00067 delete m_render;
00068 m_created_render = true;
00069 m_render = NULL;
00070 }
00071 }
00072
00073 void MythVDPAUPainter::FreeResources(void)
00074 {
00075 ClearCache();
00076 DeleteBitmaps();
00077 }
00078
00079 void MythVDPAUPainter::Begin(QPaintDevice *parent)
00080 {
00081 if (!m_render)
00082 {
00083 if (!InitVDPAU(parent))
00084 {
00085 LOG(VB_GENERAL, LOG_ERR, "Failed to create VDPAU render.");
00086 return;
00087 }
00088 }
00089
00090 if (m_render->WasPreempted())
00091 ClearCache();
00092 DeleteBitmaps();
00093
00094 if (m_target)
00095 m_render->DrawBitmap(0, m_target, NULL, NULL);
00096 else if (m_swap_control)
00097 m_render->WaitForFlip();
00098
00099 MythPainter::Begin(parent);
00100 }
00101
00102 void MythVDPAUPainter::End(void)
00103 {
00104 if (m_render && m_swap_control)
00105 m_render->Flip();
00106 MythPainter::End();
00107 }
00108
00109 void MythVDPAUPainter::ClearCache(void)
00110 {
00111 LOG(VB_GENERAL, LOG_INFO, LOC + "Clearing VDPAU painter cache.");
00112
00113 QMutexLocker locker(&m_bitmapDeleteLock);
00114 QMapIterator<MythImage *, uint32_t> it(m_ImageBitmapMap);
00115 while (it.hasNext())
00116 {
00117 it.next();
00118 m_bitmapDeleteList.push_back(m_ImageBitmapMap[it.key()]);
00119 m_ImageExpireList.remove(it.key());
00120 }
00121 m_ImageBitmapMap.clear();
00122 }
00123
00124 void MythVDPAUPainter::DeleteBitmaps(void)
00125 {
00126 QMutexLocker locker(&m_bitmapDeleteLock);
00127 while (!m_bitmapDeleteList.empty())
00128 {
00129 uint bitmap = m_bitmapDeleteList.front();
00130 m_bitmapDeleteList.pop_front();
00131 m_HardwareCacheSize -= m_render->GetBitmapSize(bitmap);
00132 m_render->DestroyBitmapSurface(bitmap);
00133 }
00134 }
00135
00136 void MythVDPAUPainter::DrawImage(const QRect &r, MythImage *im,
00137 const QRect &src, int alpha)
00138 {
00139 if (m_render)
00140 m_render->DrawBitmap(GetTextureFromCache(im), m_target,
00141 &src, &r , kVDPBlendNormal,
00142 alpha, 255, 255, 255);
00143 }
00144
00145 void MythVDPAUPainter::DeleteFormatImagePriv(MythImage *im)
00146 {
00147 if (m_ImageBitmapMap.contains(im))
00148 {
00149 QMutexLocker locker(&m_bitmapDeleteLock);
00150 m_bitmapDeleteList.push_back(m_ImageBitmapMap[im]);
00151 m_ImageBitmapMap.remove(im);
00152 m_ImageExpireList.remove(im);
00153 }
00154 }
00155
00156 uint MythVDPAUPainter::GetTextureFromCache(MythImage *im)
00157 {
00158 if (m_ImageBitmapMap.contains(im))
00159 {
00160 if (!im->IsChanged())
00161 {
00162 m_ImageExpireList.remove(im);
00163 m_ImageExpireList.push_back(im);
00164 return m_ImageBitmapMap[im];
00165 }
00166 else
00167 {
00168 DeleteFormatImagePriv(im);
00169 }
00170 }
00171
00172 im->SetChanged(false);
00173 uint newbitmap = 0;
00174 if (m_render)
00175 newbitmap = m_render->CreateBitmapSurface(im->size());
00176
00177 if (newbitmap)
00178 {
00179 CheckFormatImage(im);
00180 m_render->UploadMythImage(newbitmap, im);
00181 m_ImageBitmapMap[im] = newbitmap;
00182 m_ImageExpireList.push_back(im);
00183 m_HardwareCacheSize += m_render->GetBitmapSize(newbitmap);
00184 while (m_HardwareCacheSize > m_MaxHardwareCacheSize)
00185 {
00186 MythImage *expiredIm = m_ImageExpireList.front();
00187 m_ImageExpireList.pop_front();
00188 DeleteFormatImagePriv(expiredIm);
00189 DeleteBitmaps();
00190 }
00191 }
00192 else
00193 {
00194 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create VDPAU UI bitmap.");
00195 }
00196
00197 return newbitmap;
00198 }