MediaPlayerPrivateBlackBerry.cpp [plain text]
#include "config.h"
#if ENABLE(VIDEO)
#include "MediaPlayerPrivateBlackBerry.h"
#include "CookieManager.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "HostWindow.h"
#include "NotImplemented.h"
#include "PlatformContextSkia.h"
#include "RenderBox.h"
#include "TimeRanges.h"
#include "WebPageClient.h"
#include <BlackBerryPlatformClient.h>
#include <set>
#include <string>
#include <wtf/text/CString.h>
#if USE(ACCELERATED_COMPOSITING)
#include "NativeImageSkia.h"
#include "VideoLayerWebKitThread.h"
#include <GLES2/gl2.h>
#endif
using namespace std;
using namespace BlackBerry::Platform;
namespace WebCore {
PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivate::create(MediaPlayer* player)
{
return adoptPtr(new MediaPlayerPrivate(player));
}
void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar)
{
registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
}
void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
{
set<string> supported = MMRPlayer::allSupportedMimeTypes();
set<string>::iterator i = supported.begin();
for (; i != supported.end(); i++)
types.add(i->c_str());
}
MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
{
if (type.isNull() || type.isEmpty()) {
LOG(Media, "MediaPlayer does not support type; type is null or empty.");
return MediaPlayer::IsNotSupported;
}
if (MMRPlayer::mimeTypeSupported(type.ascii().data())) {
LOG(Media, "MediaPlayer supports type; cache contains type '%s'.", type.ascii().data());
return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported;
}
LOG(Media, "MediaPlayer does not support type; cache doesn't contain type '%s'.", type.ascii().data());
return MediaPlayer::IsNotSupported;
}
void MediaPlayerPrivate::notifyAppActivatedEvent(bool activated)
{
MMRPlayer::notifyAppActivatedEvent(activated);
}
void MediaPlayerPrivate::setCertificatePath(const String& caPath)
{
MMRPlayer::setCertificatePath(string(caPath.utf8().data()));
}
MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
: m_webCorePlayer(player)
, m_networkState(MediaPlayer::Empty)
, m_readyState(MediaPlayer::HaveNothing)
, m_fullscreenWebPageClient(0)
#if USE(ACCELERATED_COMPOSITING)
, m_bufferingTimer(this, &MediaPlayerPrivate::bufferingTimerFired)
, m_showBufferingImage(false)
, m_mediaIsBuffering(false)
#endif
, m_userDrivenSeekTimer(this, &MediaPlayerPrivate::userDrivenSeekTimerFired)
, m_lastSeekTime(0)
, m_waitMetadataTimer(this, &MediaPlayerPrivate::waitMetadataTimerFired)
, m_waitMetadataPopDialogCounter(0)
{
void* tabId = 0;
if (frameView() && frameView()->hostWindow())
tabId = frameView()->hostWindow()->platformPageClient();
#if USE(ACCELERATED_COMPOSITING)
m_platformPlayer = new MMRPlayer(this, tabId, true);
#else
m_platformPlayer = new MMRPlayer(this, tabId, false);
#endif
}
MediaPlayerPrivate::~MediaPlayerPrivate()
{
if (isFullscreen()) {
HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
element->exitFullscreen();
}
#if USE(ACCELERATED_COMPOSITING)
if (m_platformLayer)
static_cast<VideoLayerWebKitThread*>(m_platformLayer.get())->setMediaPlayer(0);
#endif
deleteGuardedObject(m_platformPlayer);
}
void MediaPlayerPrivate::load(const String& url)
{
String modifiedUrl(url);
if (modifiedUrl.startsWith("local://")) {
KURL kurl = KURL(KURL(), modifiedUrl);
kurl.setProtocol("file");
String tempPath(BlackBerry::Platform::Client::get()->getApplicationLocalDirectory().c_str());
tempPath.append(kurl.path());
kurl.setPath(tempPath);
modifiedUrl = kurl.string();
}
if (modifiedUrl.startsWith("file://")) {
modifiedUrl = decodeURLEscapeSequences(modifiedUrl);
}
String cookiePairs;
if (!url.isEmpty())
cookiePairs = cookieManager().getCookie(KURL(ParsedURLString, url.utf8().data()), WithHttpOnlyCookies);
if (!cookiePairs.isEmpty() && cookiePairs.utf8().data())
m_platformPlayer->load(modifiedUrl.utf8().data(), userAgent(modifiedUrl).utf8().data(), cookiePairs.utf8().data());
else
m_platformPlayer->load(modifiedUrl.utf8().data(), userAgent(modifiedUrl).utf8().data(), 0);
}
void MediaPlayerPrivate::cancelLoad()
{
m_platformPlayer->cancelLoad();
}
void MediaPlayerPrivate::prepareToPlay()
{
m_platformPlayer->prepareToPlay();
}
void MediaPlayerPrivate::play()
{
m_platformPlayer->play();
}
void MediaPlayerPrivate::pause()
{
m_platformPlayer->pause();
}
bool MediaPlayerPrivate::supportsFullscreen() const
{
return true;
}
IntSize MediaPlayerPrivate::naturalSize() const
{
double pixelWidth = static_cast<double>(m_platformPlayer->pixelWidth());
double pixelHeight = static_cast<double>(m_platformPlayer->pixelHeight());
if (!m_platformPlayer->pixelWidth() || !m_platformPlayer->pixelHeight())
pixelWidth = pixelHeight = 1.0;
double adjustedSourceWidth = static_cast<double>(m_platformPlayer->sourceWidth()) * pixelWidth / pixelHeight;
return IntSize(static_cast<int>(adjustedSourceWidth + 0.5), m_platformPlayer->sourceHeight());
}
bool MediaPlayerPrivate::hasVideo() const
{
return m_platformPlayer->hasVideo();
}
bool MediaPlayerPrivate::hasAudio() const
{
return m_platformPlayer->hasAudio();
}
void MediaPlayerPrivate::setVisible(bool)
{
notImplemented();
}
float MediaPlayerPrivate::duration() const
{
return m_platformPlayer->duration();
}
float MediaPlayerPrivate::currentTime() const
{
return m_userDrivenSeekTimer.isActive() ? m_lastSeekTime: m_platformPlayer->currentTime();
}
static const double SeekSubmissionDelay = 0.1;
void MediaPlayerPrivate::seek(float time)
{
m_lastSeekTime = time;
if (!m_userDrivenSeekTimer.isActive())
m_userDrivenSeekTimer.startOneShot(SeekSubmissionDelay);
}
void MediaPlayerPrivate::userDrivenSeekTimerFired(Timer<MediaPlayerPrivate>*)
{
m_platformPlayer->seek(m_lastSeekTime);
}
bool MediaPlayerPrivate::seeking() const
{
return false;
}
void MediaPlayerPrivate::setRate(float rate)
{
m_platformPlayer->setRate(rate);
}
bool MediaPlayerPrivate::paused() const
{
return m_platformPlayer->paused();
}
void MediaPlayerPrivate::setVolume(float volume)
{
m_platformPlayer->setVolume(volume);
}
MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const
{
return m_networkState;
}
MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const
{
return m_readyState;
}
float MediaPlayerPrivate::maxTimeSeekable() const
{
return m_platformPlayer->maxTimeSeekable();
}
PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const
{
RefPtr<TimeRanges> timeRanges = TimeRanges::create();
if (float bufferLoaded = m_platformPlayer->bufferLoaded())
timeRanges->add(0, bufferLoaded);
return timeRanges.release();
}
unsigned MediaPlayerPrivate::bytesLoaded() const
{
notImplemented();
return 0;
}
void MediaPlayerPrivate::setSize(const IntSize&)
{
notImplemented();
}
void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect)
{
#if USE(ACCELERATED_COMPOSITING)
if (!context)
m_platformPlayer->notifyOutputUpdate(BlackBerry::Platform::IntRect(rect.x(), rect.y(), rect.width(), rect.height()));
return;
#endif
if (!hasVideo() || context->paintingDisabled() || !m_webCorePlayer->visible())
return;
PlatformGraphicsContext* graphics = context->platformContext();
ASSERT(graphics);
BlackBerry::Platform::IntRect platformRect(rect.x(), rect.y(), rect.width(), rect.height());
IntRect clippedRect = frameView()->windowClipRect();
BlackBerry::Platform::IntRect platformWindowClipRect(clippedRect.x(), clippedRect.y(), clippedRect.width(), clippedRect.height());
m_platformPlayer->paint(graphics->canvas(), platformRect, platformWindowClipRect);
}
bool MediaPlayerPrivate::hasAvailableVideoFrame() const
{
return m_platformPlayer->hasAvailableVideoFrame();
}
bool MediaPlayerPrivate::hasSingleSecurityOrigin() const
{
return false;
}
MediaPlayer::MovieLoadType MediaPlayerPrivate::movieLoadType() const
{
return static_cast<MediaPlayer::MovieLoadType>(m_platformPlayer->movieLoadType());
}
String MediaPlayerPrivate::userAgent(const String& url) const
{
HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
Document* topdoc = element->document()->topDocument();
ASSERT(topdoc->frame());
ASSERT(topdoc->frame()->loader());
if (topdoc->frame())
return topdoc->frame()->loader()->userAgent(KURL(KURL(), url));
return String();
}
void MediaPlayerPrivate::resizeSourceDimensions()
{
if (!m_webCorePlayer)
return;
HTMLMediaElement* client = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
if (!client || !client->isVideo())
return;
RenderObject* o = client->renderer();
if (!o)
return;
if (!hasVideo()) {
IntRect rect = o->enclosingBox()->contentBoxRect();
static const int playbookMinAudioElementWidth = 300;
static const int playbookMinAudioElementHeight = 32;
int newWidth = max(rect.width(), playbookMinAudioElementWidth);
int newHeight = max(rect.height(), playbookMinAudioElementHeight);
char attrString[12];
sprintf(attrString, "%d", newWidth);
client->setAttribute(HTMLNames::widthAttr, attrString);
sprintf(attrString, "%d", newHeight);
client->setAttribute(HTMLNames::heightAttr, attrString);
}
if (m_platformPlayer->sourceWidth() && m_platformPlayer->sourceHeight())
return;
IntRect rect = o->enclosingBox()->contentBoxRect();
m_platformPlayer->setSourceDimension(rect.width(), rect.height());
}
void MediaPlayerPrivate::setFullscreenWebPageClient(BlackBerry::WebKit::WebPageClient* client)
{
if (m_fullscreenWebPageClient == client)
return;
m_fullscreenWebPageClient = client;
m_platformPlayer->toggleFullscreen(client);
if (!client)
m_webCorePlayer->repaint();
}
BlackBerry::Platform::Graphics::Window* MediaPlayerPrivate::getWindow()
{
return m_platformPlayer->getWindow();
}
BlackBerry::Platform::Graphics::Window* MediaPlayerPrivate::getPeerWindow(const char* uniqueID) const
{
return m_platformPlayer->getPeerWindow(uniqueID);
}
int MediaPlayerPrivate::getWindowPosition(unsigned& x, unsigned& y, unsigned& width, unsigned& height) const
{
return m_platformPlayer->getWindowPosition(x, y, width, height);
}
const char* MediaPlayerPrivate::mmrContextName()
{
return m_platformPlayer->mmrContextName();
}
float MediaPlayerPrivate::percentLoaded()
{
if (!m_platformPlayer->duration())
return 0;
float buffered = 0;
RefPtr<TimeRanges> timeRanges = this->buffered();
for (unsigned i = 0; i < timeRanges->length(); ++i) {
ExceptionCode ignoredException;
float start = timeRanges->start(i, ignoredException);
float end = timeRanges->end(i, ignoredException);
buffered += end - start;
}
float loaded = buffered / m_platformPlayer->duration();
return loaded;
}
unsigned MediaPlayerPrivate::sourceWidth()
{
return m_platformPlayer->sourceWidth();
}
unsigned MediaPlayerPrivate::sourceHeight()
{
return m_platformPlayer->sourceHeight();
}
void MediaPlayerPrivate::setAllowPPSVolumeUpdates(bool allow)
{
return m_platformPlayer->setAllowPPSVolumeUpdates(allow);
}
void MediaPlayerPrivate::updateStates()
{
MediaPlayer::NetworkState oldNetworkState = m_networkState;
MediaPlayer::ReadyState oldReadyState = m_readyState;
MMRPlayer::Error currentError = m_platformPlayer->error();
HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
if (currentError != MMRPlayer::MediaOK) {
m_readyState = MediaPlayer::HaveNothing;
if (currentError == MMRPlayer::MediaDecodeError)
m_networkState = MediaPlayer::DecodeError;
else if (currentError == MMRPlayer::MediaMetaDataError
|| currentError == MMRPlayer::MediaAudioReceiveError
|| currentError == MMRPlayer::MediaVideoReceiveError)
m_networkState = MediaPlayer::NetworkError;
} else {
switch (m_platformPlayer->mediaState()) {
case MMRPlayer::MMRPlayStateIdle:
m_networkState = MediaPlayer::Idle;
break;
case MMRPlayer::MMRPlayStatePlaying:
m_networkState = MediaPlayer::Loading;
break;
case MMRPlayer::MMRPlayStateStopped:
m_networkState = MediaPlayer::Idle;
break;
case MMRPlayer::MMRPlayStateUnknown:
default:
break;
}
switch (m_platformPlayer->state()) {
case MMRPlayer::MP_STATE_IDLE:
#if USE(ACCELERATED_COMPOSITING)
setBuffering(false);
m_mediaIsBuffering = false;
#endif
if (isFullscreen())
element->exitFullscreen();
break;
case MMRPlayer::MP_STATE_ACTIVE:
#if USE(ACCELERATED_COMPOSITING)
m_showBufferingImage = false;
m_mediaIsBuffering = false;
#endif
break;
case MMRPlayer::MP_STATE_UNSUPPORTED:
break;
default:
break;
}
if ((duration() || movieLoadType() == MediaPlayer::LiveStream)
&& m_readyState != MediaPlayer::HaveEnoughData)
m_readyState = MediaPlayer::HaveEnoughData;
}
if (m_readyState != oldReadyState) {
m_webCorePlayer->readyStateChanged();
#if USE(ACCELERATED_COMPOSITING)
if (!m_platformLayer)
m_platformLayer = VideoLayerWebKitThread::create(m_webCorePlayer);
#endif
}
if (m_networkState != oldNetworkState)
m_webCorePlayer->networkStateChanged();
}
void MediaPlayerPrivate::onStateChanged(MMRPlayer::MpState)
{
updateStates();
}
void MediaPlayerPrivate::onMediaStatusChanged(MMRPlayer::MMRPlayState)
{
updateStates();
}
void MediaPlayerPrivate::onError(MMRPlayer::Error type)
{
updateStates();
}
void MediaPlayerPrivate::onDurationChanged(float duration)
{
updateStates();
m_webCorePlayer->durationChanged();
}
void MediaPlayerPrivate::onTimeChanged(float)
{
m_webCorePlayer->timeChanged();
}
void MediaPlayerPrivate::onPauseStateChanged()
{
if (!isFullscreen())
return;
HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
if (m_platformPlayer->isPaused())
element->pause();
else {
m_platformPlayer->processPauseTimeoutIfNecessary();
element->play();
}
}
void MediaPlayerPrivate::onRateChanged(float)
{
m_webCorePlayer->rateChanged();
}
void MediaPlayerPrivate::onVolumeChanged(float volume)
{
m_webCorePlayer->volumeChanged(volume);
}
void MediaPlayerPrivate::onRepaint()
{
m_webCorePlayer->repaint();
}
void MediaPlayerPrivate::onSizeChanged()
{
resizeSourceDimensions();
if (hasVideo())
m_webCorePlayer->sizeChanged();
}
void MediaPlayerPrivate::onPlayNotified()
{
if (HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()))
element->play();
}
void MediaPlayerPrivate::onPauseNotified()
{
if (HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient()))
element->pause();
}
static const int popupDialogInterval = 10;
static const double checkMetadataReadyInterval = 0.5;
void MediaPlayerPrivate::onWaitMetadataNotified(bool hasFinished, int timeWaited)
{
if (!hasFinished) {
if (!m_waitMetadataTimer.isActive()) {
m_waitMetadataPopDialogCounter = static_cast<int>(timeWaited / checkMetadataReadyInterval);
m_waitMetadataTimer.startOneShot(checkMetadataReadyInterval);
}
} else if (m_waitMetadataTimer.isActive()) {
m_waitMetadataTimer.stop();
m_waitMetadataPopDialogCounter = 0;
}
}
void MediaPlayerPrivate::waitMetadataTimerFired(Timer<MediaPlayerPrivate>*)
{
if (m_platformPlayer->isMetadataReady()) {
m_platformPlayer->playWithMetadataReady();
m_waitMetadataPopDialogCounter = 0;
return;
}
static const int hitTimeToPopupDialog = static_cast<int>(popupDialogInterval / checkMetadataReadyInterval);
m_waitMetadataPopDialogCounter++;
if (m_waitMetadataPopDialogCounter < hitTimeToPopupDialog) {
m_waitMetadataTimer.startOneShot(checkMetadataReadyInterval);
return;
}
m_waitMetadataPopDialogCounter = 0;
int wait = showErrorDialog(MMRPlayer::MediaMetaDataTimeoutError);
if (!wait)
onPauseNotified();
else {
if (m_platformPlayer->isMetadataReady())
m_platformPlayer->playWithMetadataReady();
else
m_waitMetadataTimer.startOneShot(checkMetadataReadyInterval);
}
}
#if USE(ACCELERATED_COMPOSITING)
void MediaPlayerPrivate::onBuffering(bool flag)
{
setBuffering(flag);
}
#endif
int MediaPlayerPrivate::showErrorDialog(MMRPlayer::Error type)
{
using namespace BlackBerry::WebKit;
WebPageClient::AlertType atype;
switch (type) {
case MMRPlayer::MediaOK:
atype = WebPageClient::MediaOK;
break;
case MMRPlayer::MediaDecodeError:
atype = WebPageClient::MediaDecodeError;
break;
case MMRPlayer::MediaMetaDataError:
atype = WebPageClient::MediaMetaDataError;
break;
case MMRPlayer::MediaMetaDataTimeoutError:
atype = WebPageClient::MediaMetaDataTimeoutError;
break;
case MMRPlayer::MediaNoMetaDataError:
atype = WebPageClient::MediaNoMetaDataError;
break;
case MMRPlayer::MediaVideoReceiveError:
atype = WebPageClient::MediaVideoReceiveError;
break;
case MMRPlayer::MediaAudioReceiveError:
atype = WebPageClient::MediaAudioReceiveError;
break;
case MMRPlayer::MediaInvalidError:
atype = WebPageClient::MediaInvalidError;
break;
default:
LOG(Media, "Alert type does not exist.");
return -1;
}
int rc = 0;
if (frameView() && frameView()->hostWindow())
rc = frameView()->hostWindow()->platformPageClient()->showAlertDialog(atype);
return rc;
}
FrameView* MediaPlayerPrivate::frameView() const
{
HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
return element->document()->view();
}
BlackBerry::Platform::Graphics::Window* MediaPlayerPrivate::platformWindow()
{
if (frameView() && frameView()->hostWindow())
return frameView()->hostWindow()->platformPageClient()->platformWindow();
return 0;
}
bool MediaPlayerPrivate::isFullscreen() const
{
return m_fullscreenWebPageClient;
}
bool MediaPlayerPrivate::isTabVisible() const
{
if (frameView() && frameView()->hostWindow())
return frameView()->hostWindow()->platformPageClient()->isVisible();
return true;
}
#if USE(ACCELERATED_COMPOSITING)
static const double BufferingAnimationDelay = 1.0 / 24;
static char* s_bufferingImageData = 0;
static int s_bufferingImageWidth = 0;
static int s_bufferingImageHeight = 0;
PlatformMedia MediaPlayerPrivate::platformMedia() const
{
PlatformMedia pm;
pm.type = PlatformMedia::QNXMediaPlayerType;
pm.media.qnxMediaPlayer = const_cast<MediaPlayerPrivate*>(this);
return pm;
}
PlatformLayer* MediaPlayerPrivate::platformLayer() const
{
if (m_platformLayer)
return m_platformLayer.get();
return 0;
}
static void loadBufferingImageData()
{
static bool loaded = false;
if (!loaded) {
static Image* bufferingIcon = Image::loadPlatformResource("vidbuffer").leakRef();
NativeImageSkia* nativeImage = bufferingIcon->nativeImageForCurrentFrame();
if (!nativeImage)
return;
if (!nativeImage->isDataComplete())
return;
loaded = true;
nativeImage->bitmap().lockPixels();
int bufSize = nativeImage->bitmap().width() * nativeImage->bitmap().height() * 4;
s_bufferingImageWidth = nativeImage->bitmap().width();
s_bufferingImageHeight = nativeImage->bitmap().height();
s_bufferingImageData = static_cast<char*>(malloc(bufSize));
memcpy(s_bufferingImageData, nativeImage->bitmap().getPixels(), bufSize);
nativeImage->bitmap().unlockPixels();
bufferingIcon->deref();
}
}
void MediaPlayerPrivate::bufferingTimerFired(Timer<MediaPlayerPrivate>*)
{
if (m_showBufferingImage) {
if (!isFullscreen() && m_platformLayer)
m_platformLayer->setNeedsDisplay();
m_bufferingTimer.startOneShot(BufferingAnimationDelay);
}
}
void MediaPlayerPrivate::setBuffering(bool buffering)
{
if (!hasVideo())
buffering = false; if (buffering != m_showBufferingImage) {
m_showBufferingImage = buffering;
if (buffering) {
loadBufferingImageData();
m_bufferingTimer.startOneShot(BufferingAnimationDelay);
} else
m_bufferingTimer.stop();
if (m_platformLayer)
m_platformLayer->setNeedsDisplay();
}
}
static unsigned int allocateTextureId()
{
unsigned int texid;
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return texid;
}
void MediaPlayerPrivate::drawBufferingAnimation(const TransformationMatrix& matrix, int positionLocation, int texCoordLocation)
{
if (m_showBufferingImage && s_bufferingImageData && !isFullscreen()) {
TransformationMatrix renderMatrix = matrix;
timespec time;
clock_gettime(CLOCK_REALTIME, &time);
renderMatrix.rotate(time.tv_nsec / 1000000000.0 * 360.0);
static bool initialized = false;
static unsigned int texId = allocateTextureId();
glBindTexture(GL_TEXTURE_2D, texId);
if (!initialized) {
initialized = true;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, s_bufferingImageWidth, s_bufferingImageHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, s_bufferingImageData);
free(s_bufferingImageData);
}
float texcoords[] = { 0, 0, 0, 1, 1, 1, 1, 0 };
FloatPoint vertices[4];
float bx = s_bufferingImageWidth / 2.0;
float by = s_bufferingImageHeight / 2.0;
vertices[0] = renderMatrix.mapPoint(FloatPoint(-bx, -by));
vertices[1] = renderMatrix.mapPoint(FloatPoint(-bx, by));
vertices[2] = renderMatrix.mapPoint(FloatPoint(bx, by));
vertices[3] = renderMatrix.mapPoint(FloatPoint(bx, -by));
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
}
#endif
}
#endif // ENABLE(VIDEO)