diff options
110 files changed, 6902 insertions, 5012 deletions
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp index 3d6b0b1eaa..0f1ae8ea42 100644 --- a/camera/libcameraservice/CameraHardwareStub.cpp +++ b/camera/libcameraservice/CameraHardwareStub.cpp @@ -29,7 +29,8 @@ namespace android { CameraHardwareStub::CameraHardwareStub() : mParameters(), - mHeap(0), + mPreviewHeap(0), + mRawHeap(0), mFakeCamera(0), mPreviewFrameSize(0), mRawPictureCallback(0), @@ -62,13 +63,17 @@ void CameraHardwareStub::initDefaultParameters() void CameraHardwareStub::initHeapLocked() { - int width, height; - mParameters.getPreviewSize(&width, &height); + // Create raw heap. + int picture_width, picture_height; + mParameters.getPictureSize(&picture_width, &picture_height); + mRawHeap = new MemoryHeapBase(picture_width * 2 * picture_height); - LOGD("initHeapLocked: preview size=%dx%d", width, height); + int preview_width, preview_height; + mParameters.getPreviewSize(&preview_width, &preview_height); + LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height); // Note that we enforce yuv422 in setParameters(). - int how_big = width * height * 2; + int how_big = preview_width * preview_height * 2; // If we are being reinitialized to the same size as before, no // work needs to be done. @@ -79,15 +84,15 @@ void CameraHardwareStub::initHeapLocked() // Make a new mmap'ed heap that can be shared across processes. // use code below to test with pmem - mHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount); + mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount); // Make an IMemory for each frame so that we can reuse them in callbacks. for (int i = 0; i < kBufferCount; i++) { - mBuffers[i] = new MemoryBase(mHeap, i * mPreviewFrameSize, mPreviewFrameSize); + mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize); } - + // Recreate the fake camera to reflect the current size. delete mFakeCamera; - mFakeCamera = new FakeCamera(width, height); + mFakeCamera = new FakeCamera(preview_width, preview_height); } CameraHardwareStub::~CameraHardwareStub() @@ -99,7 +104,12 @@ CameraHardwareStub::~CameraHardwareStub() sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const { - return mHeap; + return mPreviewHeap; +} + +sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const +{ + return mRawHeap; } // --------------------------------------------------------------------------- @@ -114,7 +124,7 @@ int CameraHardwareStub::previewThread() // Find the offset within the heap of the current buffer. ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize; - sp<MemoryHeapBase> heap = mHeap; + sp<MemoryHeapBase> heap = mPreviewHeap; // this assumes the internal state of fake camera doesn't change // (or is thread safe) @@ -187,6 +197,24 @@ bool CameraHardwareStub::previewEnabled() { return mPreviewThread != 0; } +status_t CameraHardwareStub::startRecording(recording_callback cb, void* user) +{ + return UNKNOWN_ERROR; +} + +void CameraHardwareStub::stopRecording() +{ +} + +bool CameraHardwareStub::recordingEnabled() +{ + return false; +} + +void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem) +{ +} + // --------------------------------------------------------------------------- int CameraHardwareStub::beginAutoFocusThread(void *cookie) @@ -237,10 +265,9 @@ int CameraHardwareStub::pictureThread() // In the meantime just make another fake camera picture. int w, h; mParameters.getPictureSize(&w, &h); - sp<MemoryHeapBase> heap = new MemoryHeapBase(w * 2 * h); - sp<MemoryBase> mem = new MemoryBase(heap, 0, w * 2 * h); + sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h); FakeCamera cam(w, h); - cam.getNextFrameAsYuv422((uint8_t *)heap->base()); + cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base()); if (mRawPictureCallback) mRawPictureCallback(mem, mPictureCallbackCookie); } diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h index 9f5ddf13ec..0d26d47ece 100644 --- a/camera/libcameraservice/CameraHardwareStub.h +++ b/camera/libcameraservice/CameraHardwareStub.h @@ -30,10 +30,17 @@ namespace android { class CameraHardwareStub : public CameraHardwareInterface { public: virtual sp<IMemoryHeap> getPreviewHeap() const; + virtual sp<IMemoryHeap> getRawHeap() const; virtual status_t startPreview(preview_callback cb, void* user); virtual void stopPreview(); virtual bool previewEnabled(); + + virtual status_t startRecording(recording_callback cb, void* user); + virtual void stopRecording(); + virtual bool recordingEnabled(); + virtual void releaseRecordingFrame(const sp<IMemory>& mem); + virtual status_t autoFocus(autofocus_callback, void *user); virtual status_t takePicture(shutter_callback, raw_callback, @@ -87,7 +94,8 @@ private: CameraParameters mParameters; - sp<MemoryHeapBase> mHeap; + sp<MemoryHeapBase> mPreviewHeap; + sp<MemoryHeapBase> mRawHeap; sp<MemoryBase> mBuffers[kBufferCount]; FakeCamera *mFakeCamera; diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index 36c5ada97a..15e3b21aea 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -86,18 +86,19 @@ sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) LOGD("Connect E from ICameraClient %p", cameraClient->asBinder().get()); Mutex::Autolock lock(mLock); + sp<Client> client; if (mClient != 0) { sp<Client> currentClient = mClient.promote(); if (currentClient != 0) { sp<ICameraClient> currentCameraClient(currentClient->getCameraClient()); if (cameraClient->asBinder() == currentCameraClient->asBinder()) { // this is the same client reconnecting... - LOGD("Connect X same client is reconnecting..."); + LOGD("Connect X same client (%p) is reconnecting...", cameraClient->asBinder().get()); return currentClient; } else { - // it's another client... boot the previous one... - LOGD("new client connecting, booting the old one..."); - mClient.clear(); + // it's another client... reject it + LOGD("new client (%p) attempting to connect - rejected", cameraClient->asBinder().get()); + return client; } } else { // can't promote, the previous client has died... @@ -107,7 +108,7 @@ sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) } // create a new Client object - sp<Client> client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid()); + client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid()); mClient = client; #if DEBUG_CLIENT_REFERENCES // Enable tracking for this object, and track increments and decrements of @@ -151,28 +152,30 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) } CameraService::Client::Client(const sp<CameraService>& cameraService, - const sp<ICameraClient>& cameraClient, pid_t clientPid) + const sp<ICameraClient>& cameraClient, pid_t clientPid) { LOGD("Client E constructor"); mCameraService = cameraService; mCameraClient = cameraClient; mClientPid = clientPid; mHardware = openCameraHardware(); + mUseOverlay = mHardware->useOverlay(); // Callback is disabled by default - mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; + mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; LOGD("Client X constructor"); } status_t CameraService::Client::checkPid() { if (mClientPid == IPCThreadState::self()->getCallingPid()) return NO_ERROR; - LOGW("Attempt to use locked camera from different process"); + LOGW("Attempt to use locked camera (%p) from different process", getCameraClient()->asBinder().get()); return -EBUSY; } status_t CameraService::Client::lock() { + Mutex::Autolock _l(mLock); // lock camera to this client if the the camera is unlocked if (mClientPid == 0) { mClientPid = IPCThreadState::self()->getCallingPid(); @@ -184,8 +187,9 @@ status_t CameraService::Client::lock() status_t CameraService::Client::unlock() { + Mutex::Autolock _l(mLock); // allow anyone to use camera - LOGV("unlock"); + LOGV("unlock (%p)", getCameraClient()->asBinder().get()); status_t result = checkPid(); if (result == NO_ERROR) mClientPid = 0; return result; @@ -194,27 +198,40 @@ status_t CameraService::Client::unlock() status_t CameraService::Client::connect(const sp<ICameraClient>& client) { // connect a new process to the camera - LOGV("connect"); - - // hold a reference to the old client or we will deadlock if the client is - // in the same process and we hold the lock when we remove the reference - sp<ICameraClient> oldClient; + LOGV("connect (%p)", client->asBinder().get()); + + // I hate this hack, but things get really ugly when the media recorder + // service is handing back the camera to the app. The ICameraClient + // destructor will be called during the same IPC, making it look like + // the remote client is trying to disconnect. This hack temporarily + // sets the mClientPid to an invalid pid to prevent the hardware from + // being torn down. { - Mutex::Autolock _l(mLock); - if (mClientPid != 0) { - LOGW("Tried to connect to locked camera"); - return -EBUSY; - } - oldClient = mCameraClient; - // did the client actually change? - if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR; + // hold a reference to the old client or we will deadlock if the client is + // in the same process and we hold the lock when we remove the reference + sp<ICameraClient> oldClient; + { + Mutex::Autolock _l(mLock); + if (mClientPid != 0) { + LOGW("Tried to connect to locked camera"); + return -EBUSY; + } + oldClient = mCameraClient; + + // did the client actually change? + if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR; + + mCameraClient = client; + mClientPid = -1; + mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; + LOGV("connect new process (%d) to existing camera client", mClientPid); + } - LOGV("connect new process to existing camera client"); - mCameraClient = client; - mClientPid = IPCThreadState::self()->getCallingPid(); - mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; } + // the old client destructor is called when oldClient goes out of scope + // now we set the new PID to lock the interface again + mClientPid = IPCThreadState::self()->getCallingPid(); return NO_ERROR; } @@ -232,8 +249,8 @@ static void *unregister_surface(void *arg) CameraService::Client::~Client() { // tear down client - LOGD("Client E destructor"); - if (mSurface != 0) { + LOGD("Client (%p) E destructor", getCameraClient()->asBinder().get()); + if (mSurface != 0 && !mUseOverlay) { #if HAVE_ANDROID_OS pthread_t thr; // We unregister the buffers in a different thread because binder does @@ -244,7 +261,7 @@ CameraService::Client::~Client() mSurface.get()); pthread_join(thr, NULL); #else - mSurface->unregisterBuffers(); + mSurface->unregisterBuffers(); #endif } @@ -256,16 +273,22 @@ CameraService::Client::~Client() void CameraService::Client::disconnect() { - LOGD("Client E disconnect"); + LOGD("Client (%p) E disconnect from (%d)", + getCameraClient()->asBinder().get(), + IPCThreadState::self()->getCallingPid()); Mutex::Autolock lock(mLock); - if (mClientPid == 0) { + if (mClientPid <= 0) { LOGV("camera is unlocked, don't tear down hardware"); return; } - if (checkPid() != NO_ERROR) return; + if (checkPid() != NO_ERROR) { + LOGV("Different client - don't disconnect"); + return; + } mCameraService->removeClient(mCameraClient); if (mHardware != 0) { + LOGV("hardware teardown"); // Before destroying mHardware, we must make sure it's in the // idle state. mHardware->stopPreview(); @@ -288,7 +311,7 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) Mutex::Autolock surfaceLock(mSurfaceLock); // asBinder() is safe on NULL (returns NULL) if (surface->asBinder() != mSurface->asBinder()) { - if (mSurface != 0) { + if (mSurface != 0 && !mUseOverlay) { LOGD("clearing old preview surface %p", mSurface.get()); mSurface->unregisterBuffers(); } @@ -297,19 +320,20 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) return NO_ERROR; } -// set the frame callback flag to affect how the received frames from +// set the preview callback flag to affect how the received frames from // preview are handled. -void CameraService::Client::setFrameCallbackFlag(int frame_callback_flag) +void CameraService::Client::setPreviewCallbackFlag(int callback_flag) { + LOGV("setPreviewCallbackFlag"); Mutex::Autolock lock(mLock); if (checkPid() != NO_ERROR) return; - mFrameCallbackFlag = frame_callback_flag; + mPreviewCallbackFlag = callback_flag; } // start preview mode, must call setPreviewDisplay first -status_t CameraService::Client::startPreview() +status_t CameraService::Client::startCameraMode(camera_mode mode) { - LOGD("startPreview()"); + LOGD("startCameraMode(%d)", mode); /* we cannot call into mHardware with mLock held because * mHardware has callbacks onto us which acquire this lock @@ -325,37 +349,124 @@ status_t CameraService::Client::startPreview() } if (mSurface == 0) { - LOGE("setPreviewDisplay must be called before startPreview!"); + LOGE("setPreviewDisplay must be called before startCameraMode!"); return INVALID_OPERATION; } - // do nothing if preview is already started - if (mHardware->previewEnabled()) return NO_ERROR; + switch(mode) { + case CAMERA_RECORDING_MODE: + return startRecordingMode(); - // XXX: This needs to be improved. remove all hardcoded stuff + default: // CAMERA_PREVIEW_MODE + return startPreviewMode(); + } +} - int w, h; - CameraParameters params(mHardware->getParameters()); - params.getPreviewSize(&w, &h); +status_t CameraService::Client::startRecordingMode() +{ + LOGV("startRecordingMode"); + status_t ret = UNKNOWN_ERROR; + + // if preview has not been started, start preview first + if (!mHardware->previewEnabled()) { + ret = startPreviewMode(); + if (ret != NO_ERROR) { + return ret; + } + } + + // if recording has been enabled, nothing needs to be done + if (mHardware->recordingEnabled()) { + return NO_ERROR; + } + + // start recording mode + ret = mHardware->startRecording(recordingCallback, + mCameraService.get()); + if (ret != NO_ERROR) { + LOGE("mHardware->startRecording() failed with status %d", ret); + } + return ret; +} + +status_t CameraService::Client::startPreviewMode() +{ + LOGV("startPreviewMode"); + + // if preview has been enabled, nothing needs to be done + if (mHardware->previewEnabled()) { + return NO_ERROR; + } + + // start preview mode #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE debug_frame_cnt = 0; #endif + status_t ret = UNKNOWN_ERROR; + int w, h; + CameraParameters params(mHardware->getParameters()); + params.getPreviewSize(&w, &h); - status_t ret = mHardware->startPreview(previewCallback, - mCameraService.get()); - if (ret == NO_ERROR) { - mSurface->unregisterBuffers(); - mSurface->registerBuffers(w,h,w,h, - PIXEL_FORMAT_YCbCr_420_SP, - mHardware->getPreviewHeap()); - } - else LOGE("mHardware->startPreview() failed with status %d\n", - ret); + if (mUseOverlay) { + const char *format = params.getPreviewFormat(); + int fmt; + LOGD("Use Overlays"); + if (!strcmp(format, "yuv422i")) + fmt = OVERLAY_FORMAT_YCbCr_422_I; + else if (!strcmp(format, "rgb565")) + fmt = OVERLAY_FORMAT_RGB_565; + else { + LOGE("Invalid preview format for overlays"); + return -EINVAL; + } + sp<OverlayRef> ref = mSurface->createOverlay(w, h, fmt); + ret = mHardware->setOverlay(new Overlay(ref)); + if (ret != NO_ERROR) { + LOGE("mHardware->setOverlay() failed with status %d\n", ret); + return ret; + } + ret = mHardware->startPreview(NULL, mCameraService.get()); + if (ret != NO_ERROR) + LOGE("mHardware->startPreview() failed with status %d\n", ret); + + } else { + ret = mHardware->startPreview(previewCallback, + mCameraService.get()); + if (ret == NO_ERROR) { + + mSurface->unregisterBuffers(); + + uint32_t transform = 0; + if (params.getOrientation() == + CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { + LOGV("portrait mode"); + transform = ISurface::BufferHeap::ROT_90; + } + ISurface::BufferHeap buffers(w, h, w, h, + PIXEL_FORMAT_YCbCr_420_SP, + transform, + 0, + mHardware->getPreviewHeap()); + mSurface->registerBuffers(buffers); + } else { + LOGE("mHardware->startPreview() failed with status %d", ret); + } + } return ret; } +status_t CameraService::Client::startPreview() +{ + return startCameraMode(CAMERA_PREVIEW_MODE); +} + +status_t CameraService::Client::startRecording() +{ + return startCameraMode(CAMERA_RECORDING_MODE); +} + // stop preview mode void CameraService::Client::stopPreview() { @@ -372,12 +483,46 @@ void CameraService::Client::stopPreview() mHardware->stopPreview(); LOGD("stopPreview(), hardware stopped OK"); - if (mSurface != 0) { + if (mSurface != 0 && !mUseOverlay) { mSurface->unregisterBuffers(); } mPreviewBuffer.clear(); } +// stop recording mode +void CameraService::Client::stopRecording() +{ + LOGV("stopRecording()"); + + Mutex::Autolock lock(mLock); + if (checkPid() != NO_ERROR) return; + + if (mHardware == 0) { + LOGE("mHardware is NULL, returning."); + return; + } + + mHardware->stopRecording(); + LOGV("stopRecording(), hardware stopped OK"); + mPreviewBuffer.clear(); +} + +// release a recording frame +void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) +{ + LOGV("releaseRecordingFrame()"); + + Mutex::Autolock lock(mLock); + if (checkPid() != NO_ERROR) return; + + if (mHardware == 0) { + LOGE("mHardware is NULL, returning."); + return; + } + + mHardware->releaseRecordingFrame(mem); +} + bool CameraService::Client::previewEnabled() { Mutex::Autolock lock(mLock); @@ -385,6 +530,13 @@ bool CameraService::Client::previewEnabled() return mHardware->previewEnabled(); } +bool CameraService::Client::recordingEnabled() +{ + Mutex::Autolock lock(mLock); + if (mHardware == 0) return false; + return mHardware->recordingEnabled(); +} + // Safely retrieves a strong pointer to the client during a hardware callback. sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) { @@ -476,7 +628,7 @@ void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user) #endif // The strong pointer guarantees the client will exist, but no lock is held. - client->postFrame(mem); + client->postPreviewFrame(mem); #if DEBUG_CLIENT_REFERENCES //**** if the client's refcount is 1, then we are about to destroy it here, @@ -488,6 +640,18 @@ void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user) #endif } +// recording callback +void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user) +{ + LOGV("recordingCallback"); + sp<Client> client = getClientFromCookie(user); + if (client == 0) { + return; + } + // The strong pointer guarantees the client will exist, but no lock is held. + client->postRecordingFrame(mem); +} + // take a picture - image is returned in callback status_t CameraService::Client::autoFocus() { @@ -520,9 +684,6 @@ status_t CameraService::Client::takePicture() return INVALID_OPERATION; } - if (mSurface != NULL) - mSurface->unregisterBuffers(); - return mHardware->takePicture(shutterCallback, yuvPictureCallback, jpegPictureCallback, @@ -537,7 +698,29 @@ void CameraService::Client::shutterCallback(void *user) return; } + // Screen goes black after the buffer is unregistered. + if (client->mSurface != 0 && !client->mUseOverlay) { + client->mSurface->unregisterBuffers(); + } + client->postShutter(); + + // It takes some time before yuvPicture callback to be called. + // Register the buffer for raw image here to reduce latency. + if (client->mSurface != 0 && !client->mUseOverlay) { + int w, h; + CameraParameters params(client->mHardware->getParameters()); + params.getPictureSize(&w, &h); + uint32_t transform = 0; + if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { + LOGV("portrait mode"); + transform = ISurface::BufferHeap::ROT_90; + } + ISurface::BufferHeap buffers(w, h, w, h, + PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap()); + + client->mSurface->registerBuffers(buffers); + } } // picture callback - raw image ready @@ -568,15 +751,7 @@ void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem, #endif // Put the YUV version of the snapshot in the preview display. - int w, h; - CameraParameters params(client->mHardware->getParameters()); - params.getPictureSize(&w, &h); - -// Mutex::Autolock clientLock(client->mLock); - if (client->mSurface != 0) { - client->mSurface->unregisterBuffers(); - client->mSurface->registerBuffers(w,h,w,h, - PIXEL_FORMAT_YCbCr_420_SP, heap); + if (client->mSurface != 0 && !client->mUseOverlay) { client->mSurface->postBuffer(offset); } @@ -730,12 +905,22 @@ void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, si LOGE("failed to allocate space for frame callback"); return; } - mCameraClient->frameCallback(frame); + mCameraClient->previewCallback(frame); } -void CameraService::Client::postFrame(const sp<IMemory>& mem) +void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame) { - LOGV("postFrame"); + LOGV("postRecordingFrame"); + if (frame == 0) { + LOGW("frame is a null pointer"); + return; + } + mCameraClient->recordingCallback(frame); +} + +void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem) +{ + LOGV("postPreviewFrame"); if (mem == 0) { LOGW("mem is a null pointer"); return; @@ -752,31 +937,32 @@ void CameraService::Client::postFrame(const sp<IMemory>& mem) } // Is the callback enabled or not? - if (!(mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) { + if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) { // If the enable bit is off, the copy-out and one-shot bits are ignored LOGV("frame callback is diabled"); return; } // Is the received frame copied out or not? - if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) { + if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) { LOGV("frame is copied out"); copyFrameAndPostCopiedFrame(heap, offset, size); } else { LOGV("frame is directly sent out without copying"); - mCameraClient->frameCallback(mem); + mCameraClient->previewCallback(mem); } // Is this is one-shot only? - if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) { + if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) { LOGV("One-shot only, thus clear the bits and disable frame callback"); - mFrameCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK | + mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK | FRAME_CALLBACK_FLAG_COPY_OUT_MASK | FRAME_CALLBACK_FLAG_ENABLE_MASK); } } -void CameraService::Client::postError(status_t error) { +void CameraService::Client::postError(status_t error) +{ mCameraClient->errorCallback(error); } @@ -796,6 +982,11 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) AutoMutex lock(&mLock); if (mClient != 0) { sp<Client> currentClient = mClient.promote(); + sprintf(buffer, "Client (%p) PID: %d\n", + currentClient->getCameraClient()->asBinder().get(), + currentClient->mClientPid); + result.append(buffer); + write(fd, result.string(), result.size()); currentClient->mHardware->dump(fd, args); } else { result.append("No camera client yet.\n"); @@ -880,5 +1071,3 @@ status_t CameraService::onTransact( #endif // DEBUG_HEAP_LEAKS }; // namespace android - - diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index cd8c1e9a41..d9b79276a7 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -82,9 +82,9 @@ private: // pass the buffered ISurface to the camera service virtual status_t setPreviewDisplay(const sp<ISurface>& surface); - // set the frame callback flag to affect how the received frames from + // set the preview callback flag to affect how the received frames from // preview are handled. - virtual void setFrameCallbackFlag(int frame_callback_flag); + virtual void setPreviewCallbackFlag(int callback_flag); // start preview mode, must call setPreviewDisplay first virtual status_t startPreview(); @@ -95,6 +95,18 @@ private: // get preview state virtual bool previewEnabled(); + // start recording mode + virtual status_t startRecording(); + + // stop recording mode + virtual void stopRecording(); + + // get recording state + virtual bool recordingEnabled(); + + // release a recording frame + virtual void releaseRecordingFrame(const sp<IMemory>& mem); + // auto focus virtual status_t autoFocus(); @@ -120,6 +132,7 @@ private: status_t checkPid(); + static void recordingCallback(const sp<IMemory>& mem, void* user); static void previewCallback(const sp<IMemory>& mem, void* user); static void shutterCallback(void *user); static void yuvPictureCallback(const sp<IMemory>& mem, void* user); @@ -130,17 +143,28 @@ private: void postShutter(); void postRaw(const sp<IMemory>& mem); void postJpeg(const sp<IMemory>& mem); - void postFrame(const sp<IMemory>& mem); + void postPreviewFrame(const sp<IMemory>& mem); + void postRecordingFrame(const sp<IMemory>& frame); void copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size); void postError(status_t error); void postAutoFocus(bool focused); - // Ensures atomicity among the public methods + // camera operation mode + enum camera_mode { + CAMERA_PREVIEW_MODE = 0, // frame automatically released + CAMERA_RECORDING_MODE = 1, // frame has to be explicitly released by releaseRecordingFrame() + }; + status_t startCameraMode(camera_mode mode); + status_t startPreviewMode(); + status_t startRecordingMode(); + + // Ensures atomicity among the public methods mutable Mutex mLock; + // mSurfaceLock synchronizes access to mSurface between - // setPreviewSurface() and postFrame(). Note that among + // setPreviewSurface() and postPreviewFrame(). Note that among // the public methods, all accesses to mSurface are - // syncrhonized by mLock. However, postFrame() is called + // syncrhonized by mLock. However, postPreviewFrame() is called // by the CameraHardwareInterface callback, and needs to // access mSurface. It cannot hold mLock, however, because // stopPreview() may be holding that lock while attempting @@ -152,13 +176,14 @@ private: sp<CameraService> mCameraService; sp<ISurface> mSurface; sp<MemoryHeapBase> mPreviewBuffer; - int mFrameCallbackFlag; + int mPreviewCallbackFlag; // these are immutable once the object is created, // they don't need to be protected by a lock sp<ICameraClient> mCameraClient; sp<CameraHardwareInterface> mHardware; pid_t mClientPid; + bool mUseOverlay; }; // ---------------------------------------------------------------------------- diff --git a/include/GLES/egl.h b/include/GLES/egl.h deleted file mode 100644 index 08834ab8b6..0000000000 --- a/include/GLES/egl.h +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_EGL_H -#define ANDROID_EGL_H - -#include <GLES/gl.h> -#include <GLES/egltypes.h> -#include <GLES/eglnatives.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#define EGL_VERSION_1_0 1 -#define EGL_VERSION_1_1 1 -#define EGL_VERSION_1_2 1 - -#define EGL_FALSE 0 -#define EGL_TRUE 1 - -/* Errors */ -#define EGL_SUCCESS 0x3000 -#define EGL_NOT_INITIALIZED 0x3001 -#define EGL_BAD_ACCESS 0x3002 -#define EGL_BAD_ALLOC 0x3003 -#define EGL_BAD_ATTRIBUTE 0x3004 -#define EGL_BAD_CONFIG 0x3005 -#define EGL_BAD_CONTEXT 0x3006 -#define EGL_BAD_CURRENT_SURFACE 0x3007 -#define EGL_BAD_DISPLAY 0x3008 -#define EGL_BAD_MATCH 0x3009 -#define EGL_BAD_NATIVE_PIXMAP 0x300A -#define EGL_BAD_NATIVE_WINDOW 0x300B -#define EGL_BAD_PARAMETER 0x300C -#define EGL_BAD_SURFACE 0x300D -#define EGL_CONTEXT_LOST 0x300E - -/* Config attributes */ -#define EGL_BUFFER_SIZE 0x3020 -#define EGL_ALPHA_SIZE 0x3021 -#define EGL_BLUE_SIZE 0x3022 -#define EGL_GREEN_SIZE 0x3023 -#define EGL_RED_SIZE 0x3024 -#define EGL_DEPTH_SIZE 0x3025 -#define EGL_STENCIL_SIZE 0x3026 -#define EGL_CONFIG_CAVEAT 0x3027 -#define EGL_CONFIG_ID 0x3028 -#define EGL_LEVEL 0x3029 -#define EGL_MAX_PBUFFER_HEIGHT 0x302A -#define EGL_MAX_PBUFFER_PIXELS 0x302B -#define EGL_MAX_PBUFFER_WIDTH 0x302C -#define EGL_NATIVE_RENDERABLE 0x302D -#define EGL_NATIVE_VISUAL_ID 0x302E -#define EGL_NATIVE_VISUAL_TYPE 0x302F -#define EGL_SAMPLES 0x3031 -#define EGL_SAMPLE_BUFFERS 0x3032 -#define EGL_SURFACE_TYPE 0x3033 -#define EGL_TRANSPARENT_TYPE 0x3034 -#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 -#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 -#define EGL_TRANSPARENT_RED_VALUE 0x3037 -#define EGL_NONE 0x3038 -#define EGL_BIND_TO_TEXTURE_RGB 0x3039 -#define EGL_BIND_TO_TEXTURE_RGBA 0x303A -#define EGL_MIN_SWAP_INTERVAL 0x303B -#define EGL_MAX_SWAP_INTERVAL 0x303C -#define EGL_LUMINANCE_SIZE 0x303D -#define EGL_ALPHA_MASK_SIZE 0x303E -#define EGL_COLOR_BUFFER_TYPE 0x303F -#define EGL_RENDERABLE_TYPE 0x3040 - -/* Config values */ -#define EGL_DONT_CARE ((EGLint)-1) - -#define EGL_SLOW_CONFIG 0x3050 -#define EGL_NON_CONFORMANT_CONFIG 0x3051 -#define EGL_TRANSPARENT_RGB 0x3052 -#define EGL_NO_TEXTURE 0x305C -#define EGL_TEXTURE_RGB 0x305D -#define EGL_TEXTURE_RGBA 0x305E -#define EGL_TEXTURE_2D 0x305F -#define EGL_RGB_BUFFER 0x308E -#define EGL_LUMINANCE_BUFFER 0x308F - -/* Config attribute mask bits */ -#define EGL_PBUFFER_BIT 0x01 -#define EGL_PIXMAP_BIT 0x02 -#define EGL_WINDOW_BIT 0x04 -#define EGL_OPENGL_ES_BIT 0x01 -#define EGL_OPENVG_BIT 0x02 - -/* String names */ -#define EGL_VENDOR 0x3053 -#define EGL_VERSION 0x3054 -#define EGL_EXTENSIONS 0x3055 -#define EGL_CLIENT_APIS 0x308D - -/* Surface attributes */ -#define EGL_HEIGHT 0x3056 -#define EGL_WIDTH 0x3057 -#define EGL_LARGEST_PBUFFER 0x3058 -#define EGL_TEXTURE_FORMAT 0x3080 -#define EGL_TEXTURE_TARGET 0x3081 -#define EGL_MIPMAP_TEXTURE 0x3082 -#define EGL_MIPMAP_LEVEL 0x3083 -#define EGL_RENDER_BUFFER 0x3086 -#define EGL_COLORSPACE 0x3087 -#define EGL_ALPHA_FORMAT 0x3088 -#define EGL_HORIZONTAL_RESOLUTION 0x3090 -#define EGL_VERTICAL_RESOLUTION 0x3091 -#define EGL_PIXEL_ASPECT_RATIO 0x3092 -#define EGL_SWAP_BEHAVIOR 0x3093 - -#define EGL_BACK_BUFFER 0x3084 -#define EGL_SINGLE_BUFFER 0x3085 - -#define EGL_DISPLAY_SCALING 10000 - -#define EGL_UNKNOWN ((EGLint)-1) - -/* Back buffer swap behaviors */ -#define EGL_BUFFER_PRESERVED 0x3094 -#define EGL_BUFFER_DESTROYED 0x3095 - -/* CreatePbufferFromClientBuffer buffer types */ -#define EGL_OPENVG_IMAGE 0x3096 - -/* QueryContext targets */ -#define EGL_CONTEXT_CLIENT_TYPE 0x3097 - -/* BindAPI/QueryAPI targets */ -#define EGL_OPENGL_ES_API 0x30A0 -#define EGL_OPENVG_API 0x30A1 - -/* WaitNative engines */ -#define EGL_CORE_NATIVE_ENGINE 0x305B - -/* Current surfaces */ -#define EGL_DRAW 0x3059 -#define EGL_READ 0x305A - - -EGLDisplay eglGetDisplay(NativeDisplayType display); -EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor); -EGLBoolean eglTerminate(EGLDisplay dpy); - -EGLBoolean eglGetConfigs( EGLDisplay dpy, - EGLConfig *configs, - EGLint config_size, EGLint *num_config); - -EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, - EGLConfig *configs, EGLint config_size, - EGLint *num_config); - -EGLBoolean eglGetConfigAttrib( EGLDisplay dpy, EGLConfig config, - EGLint attribute, EGLint *value); - -EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, - NativeWindowType window, - const EGLint *attrib_list); - -EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, - NativePixmapType pixmap, - const EGLint *attrib_list); - -EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, - const EGLint *attrib_list); - -EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface); - -EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, - EGLint attribute, EGLint *value); - -EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, - EGLContext share_list, const EGLint *attrib_list); - -EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx); - -EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, - EGLSurface read, EGLContext ctx); - -EGLContext eglGetCurrentContext(void); -EGLSurface eglGetCurrentSurface(EGLint readdraw); -EGLDisplay eglGetCurrentDisplay(void); -EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, - EGLint attribute, EGLint *value); - -EGLBoolean eglWaitGL(void); -EGLBoolean eglWaitNative(EGLint engine); -EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw); -EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, - NativePixmapType target); - -EGLint eglGetError(void); -const char* eglQueryString(EGLDisplay dpy, EGLint name); -void (*eglGetProcAddress (const char *procname))(); - -/* ---------------------------------------------------------------------------- - * EGL 1.1 - * ---------------------------------------------------------------------------- - */ - -EGLBoolean eglSurfaceAttrib( - EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); -EGLBoolean eglBindTexImage( - EGLDisplay dpy, EGLSurface surface, EGLint buffer); -EGLBoolean eglReleaseTexImage( - EGLDisplay dpy, EGLSurface surface, EGLint buffer); - -EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval); - -/* ---------------------------------------------------------------------------- - * EGL 1.2 - * ---------------------------------------------------------------------------- - */ - -EGLBoolean eglBindAPI(EGLenum api); -EGLenum eglQueryAPI(void); -EGLBoolean eglWaitClient(void); -EGLBoolean eglReleaseThread(void); -EGLSurface eglCreatePbufferFromClientBuffer( - EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, - EGLConfig config, const EGLint *attrib_list); - -/* ---------------------------------------------------------------------------- - * Android extentions - * ---------------------------------------------------------------------------- - */ - -EGLBoolean eglSwapRectangleANDROID(EGLDisplay dpy, EGLSurface draw, - EGLint l, EGLint t, EGLint w, EGLint h); - -EGLBoolean eglCopyFrontToBackANDROID(EGLDisplay dpy, - EGLSurface surface, - EGLint l, EGLint t, EGLint w, EGLint h); - -const char* eglQueryStringConfigANDROID( - EGLDisplay dpy, EGLConfig config, EGLint name); - -void* eglGetRenderBufferAddressANDROID(EGLDisplay dpy, EGLSurface surface); - -EGLBoolean eglCopyBitsANDROID(EGLDisplay dpy, - NativeWindowType draw, EGLint x, EGLint y, - NativeWindowType read, - EGLint crop_x, EGLint crop_y, EGLint crop_w, EGLint crop_h, - EGLint flags); - - -#ifdef __cplusplus -} -#endif - - -#endif /*ANDROID_EGL_H*/ diff --git a/include/GLES/egltypes.h b/include/GLES/egltypes.h deleted file mode 100644 index 698239b210..0000000000 --- a/include/GLES/egltypes.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_EGL_TYPES_H -#define ANDROID_EGL_TYPES_H - -#include <sys/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef unsigned int EGLBoolean; -typedef int32_t EGLint; -typedef int EGLenum; -typedef void *EGLDisplay; -typedef void *EGLConfig; -typedef void *EGLSurface; -typedef void *EGLContext; -typedef void *EGLClientBuffer; - -#define EGL_DEFAULT_DISPLAY ((NativeDisplayType)0) - -#define EGL_NO_CONTEXT ((EGLContext)0) -#define EGL_NO_DISPLAY ((EGLDisplay)0) -#define EGL_NO_SURFACE ((EGLSurface)0) - - -#ifdef __cplusplus -} -#endif - - -#endif /* ANDROID_EGL_TYPES_H */ diff --git a/include/GLES/gl.h b/include/GLES/gl.h deleted file mode 100644 index 50b6ac43f8..0000000000 --- a/include/GLES/gl.h +++ /dev/null @@ -1,639 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __gl_h_ -#define __gl_h_ - -#include <stdint.h> -#include <sys/types.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/*****************************************************************************/ - -typedef int8_t GLbyte; // b -typedef int16_t GLshort; // s -typedef int32_t GLint; // i -typedef ssize_t GLsizei; // i -typedef int32_t GLfixed; // x -typedef int32_t GLclampx; // x -typedef float GLfloat; // f -typedef float GLclampf; // f -typedef uint8_t GLubyte; // ub -typedef uint8_t GLboolean; // ub -typedef uint16_t GLushort; // us -typedef uint32_t GLuint; // ui -typedef unsigned int GLenum; // ui -typedef unsigned int GLbitfield; // ui -typedef void GLvoid; -typedef intptr_t GLintptr; -typedef int GLsizeiptr; -typedef GLintptr GLintptrARB; -typedef GLsizeiptr GLsizeiptrARB; - -/*****************************************************************************/ - -#define GL_VERSION_ES_CM_1_0 1 -#define GL_VERSION_ES_CL_1_0 1 -#define GL_VERSION_ES_CM_1_1 1 -#define GL_VERSION_ES_CL_1_1 1 - -#define GL_OES_byte_coordinates 1 -#define GL_OES_fixed_point 1 -#define GL_OES_single_precision 1 -#define GL_OES_read_format 1 -#define GL_OES_compressed_paletted_texture 1 -#define GL_OES_draw_texture 1 -#define GL_OES_matrix_get 1 -#define GL_OES_query_matrix 1 -#define GL_OES_vertex_buffer_object 1 -#define GL_OES_point_size_array 1 -#define GL_OES_point_sprite 1 -#define GL_ARB_texture_non_power_of_two 1 - -/*****************************************************************************/ -/* OpenGL ES 1.0 names */ - -#define GL_FALSE 0 -#define GL_TRUE 1 - -/* begin mode */ -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 - -/* clear mask */ -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_COLOR_BUFFER_BIT 0x00004000 - -/* enable/disable */ -#define GL_FOG 0x0B60 -#define GL_LIGHTING 0x0B50 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_CULL_FACE 0x0B44 -#define GL_ALPHA_TEST 0x0BC0 -#define GL_BLEND 0x0BE2 -#define GL_COLOR_LOGIC_OP 0x0BF2 -#define GL_DITHER 0x0BD0 -#define GL_STENCIL_TEST 0x0B90 -#define GL_DEPTH_TEST 0x0B71 -#define GL_POINT_SMOOTH 0x0B10 -#define GL_LINE_SMOOTH 0x0B20 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_COLOR_MATERIAL 0x0B57 -#define GL_NORMALIZE 0x0BA1 -#define GL_RESCALE_NORMAL 0x803A -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_VERTEX_ARRAY 0x8074 -#define GL_NORMAL_ARRAY 0x8075 -#define GL_COLOR_ARRAY 0x8076 -#define GL_TEXTURE_COORD_ARRAY 0x8078 -#define GL_MULTISAMPLE 0x809D -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_ALPHA_TO_ONE 0x809F -#define GL_SAMPLE_COVERAGE 0x80A0 - -/* gets */ -#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 -#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#define GL_MAX_LIGHTS 0x0D31 -#define GL_MAX_CLIP_PLANES 0x0D32 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 -#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 -#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_MAX_TEXTURE_UNITS 0x84E2 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_ALPHA_BITS 0x0D55 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 - -/* clip planes */ -#define GL_CLIP_PLANE0 0x3000 -#define GL_CLIP_PLANE1 0x3001 -#define GL_CLIP_PLANE2 0x3002 -#define GL_CLIP_PLANE3 0x3003 -#define GL_CLIP_PLANE4 0x3004 -#define GL_CLIP_PLANE5 0x3005 - -/* errors */ -#define GL_NO_ERROR 0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 -#define GL_OUT_OF_MEMORY 0x0505 - -/* fog */ -#define GL_EXP 0x0800 -#define GL_EXP2 0x0801 -#define GL_FOG_DENSITY 0x0B62 -#define GL_FOG_START 0x0B63 -#define GL_FOG_END 0x0B64 -#define GL_FOG_MODE 0x0B65 -#define GL_FOG_COLOR 0x0B66 - -/* culling */ -#define GL_CW 0x0900 -#define GL_CCW 0x0901 - -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 - -/* hints */ -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 - -#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 -#define GL_POINT_SMOOTH_HINT 0x0C51 -#define GL_LINE_SMOOTH_HINT 0x0C52 -#define GL_POLYGON_SMOOTH_HINT 0x0C53 -#define GL_FOG_HINT 0x0C54 -#define GL_GENERATE_MIPMAP_HINT 0x8192 - -/* lights */ -#define GL_LIGHT_MODEL_AMBIENT 0x0B53 -#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 - -#define GL_AMBIENT 0x1200 -#define GL_DIFFUSE 0x1201 -#define GL_SPECULAR 0x1202 -#define GL_POSITION 0x1203 -#define GL_SPOT_DIRECTION 0x1204 -#define GL_SPOT_EXPONENT 0x1205 -#define GL_SPOT_CUTOFF 0x1206 -#define GL_CONSTANT_ATTENUATION 0x1207 -#define GL_LINEAR_ATTENUATION 0x1208 -#define GL_QUADRATIC_ATTENUATION 0x1209 - -#define GL_LIGHT0 0x4000 -#define GL_LIGHT1 0x4001 -#define GL_LIGHT2 0x4002 -#define GL_LIGHT3 0x4003 -#define GL_LIGHT4 0x4004 -#define GL_LIGHT5 0x4005 -#define GL_LIGHT6 0x4006 -#define GL_LIGHT7 0x4007 - -/* material */ -#define GL_EMISSION 0x1600 -#define GL_SHININESS 0x1601 -#define GL_AMBIENT_AND_DIFFUSE 0x1602 - -/* matrix */ -#define GL_MODELVIEW 0x1700 -#define GL_PROJECTION 0x1701 -#define GL_TEXTURE 0x1702 - -/* types */ -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_FLOAT 0x1406 -#define GL_FIXED 0x140C - -/* pixel formats */ -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A - -/* pixel store */ -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_PACK_ALIGNMENT 0x0D05 - -/* pixel types */ -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 - -/* logic op */ -#define GL_CLEAR 0x1500 // 0 -#define GL_AND 0x1501 // s & d -#define GL_AND_REVERSE 0x1502 // s & ~d -#define GL_COPY 0x1503 // s -#define GL_AND_INVERTED 0x1504 // ~s & d -#define GL_NOOP 0x1505 // d -#define GL_XOR 0x1506 // s ^ d -#define GL_OR 0x1507 // s | d -#define GL_NOR 0x1508 // ~(s | d) -#define GL_EQUIV 0x1509 // ~(s ^ d) -#define GL_INVERT 0x150A // ~d -#define GL_OR_REVERSE 0x150B // s | ~d -#define GL_COPY_INVERTED 0x150C // ~s -#define GL_OR_INVERTED 0x150D // ~s | d -#define GL_NAND 0x150E // ~(s & d) -#define GL_SET 0x150F // 1 - -/* shade model */ -#define GL_FLAT 0x1D00 -#define GL_SMOOTH 0x1D01 - -/* strings */ -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 - -/* stencil */ -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 - -/* alpha & stencil */ -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 - -/* blending equation & function */ -#define GL_ZERO 0 // SD -#define GL_ONE 1 // SD -#define GL_SRC_COLOR 0x0300 // D -#define GL_ONE_MINUS_SRC_COLOR 0x0301 // D -#define GL_SRC_ALPHA 0x0302 // SD -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 // SD -#define GL_DST_ALPHA 0x0304 // SD -#define GL_ONE_MINUS_DST_ALPHA 0x0305 // SD -#define GL_DST_COLOR 0x0306 // S -#define GL_ONE_MINUS_DST_COLOR 0x0307 // S -#define GL_SRC_ALPHA_SATURATE 0x0308 // S - -/* Texture parameter name */ -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_GENERATE_MIPMAP 0x8191 -#define GL_TEXTURE_CROP_RECT_OES 0x8B9D - -/* Texture Filter */ -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 - -/* Texture Wrap Mode */ -#define GL_CLAMP 0x2900 -#define GL_REPEAT 0x2901 -#define GL_CLAMP_TO_EDGE 0x812F - -/* Texture Env Mode */ -#define GL_REPLACE 0x1E01 -#define GL_MODULATE 0x2100 -#define GL_DECAL 0x2101 -#define GL_ADD 0x0104 - -/* Texture Env Parameter */ -#define GL_TEXTURE_ENV_MODE 0x2200 -#define GL_TEXTURE_ENV_COLOR 0x2201 - -/* Texture Env Target */ -#define GL_TEXTURE_ENV 0x2300 - -/* TMUs */ -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF - -/*****************************************************************************/ -/* OpenGL ES 1.1 additions */ - -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 - -#define GL_STATIC_DRAW 0x88E4 -#define GL_DYNAMIC_DRAW 0x88E8 - -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 - -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 -#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 -#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 -#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 -#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A - -/*****************************************************************************/ -/* Required extensions */ - -#define GL_PALETTE4_RGB8_OES 0x8B90 -#define GL_PALETTE4_RGBA8_OES 0x8B91 -#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 -#define GL_PALETTE4_RGBA4_OES 0x8B93 -#define GL_PALETTE4_RGB5_A1_OES 0x8B94 -#define GL_PALETTE8_RGB8_OES 0x8B95 -#define GL_PALETTE8_RGBA8_OES 0x8B96 -#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 -#define GL_PALETTE8_RGBA4_OES 0x8B98 -#define GL_PALETTE8_RGB5_A1_OES 0x8B99 - -#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B - -#define GL_POINT_SPRITE_OES 0x8861 -#define GL_COORD_REPLACE_OES 0x8862 - -#define GL_POINT_SIZE_ARRAY_OES 0x8B9C -#define GL_POINT_SIZE_ARRAY_TYPE_OES 0x898A -#define GL_POINT_SIZE_ARRAY_STRIDE_OES 0x898B -#define GL_POINT_SIZE_ARRAY_POINTER_OES 0x898C -#define GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES 0x8B9F - -/*****************************************************************************/ -/* Extensions */ - -#define GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES 0x898D -#define GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES 0x898E -#define GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES 0x898F - -#define GL_DIRECT_TEXTURE_2D_QUALCOMM 0x7E80 - - - - -/*****************************************************************************/ -/* OpenGL ES 1.0 functions */ - -void glActiveTexture(GLenum texture); -void glAlphaFunc(GLenum func, GLclampf ref); -void glAlphaFuncx(GLenum func, GLclampx ref); -void glBindTexture(GLenum target, GLuint texture); -void glBlendFunc(GLenum sfactor, GLenum dfactor); -void glClear(GLbitfield mask); -void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -void glClearColorx(GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha); -void glClearDepthf(GLclampf depth); -void glClearDepthx(GLclampx depth); -void glClearStencil(GLint s); -void glClientActiveTexture(GLenum texture); -void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void glColor4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); -void glColorMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a); -void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLint border, - GLsizei imageSize, const GLvoid *data); -void glCompressedTexSubImage2D( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLsizei imageSize, - const GLvoid *data); -void glCopyTexImage2D( GLenum target, GLint level, GLenum internalformat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border); -void glCopyTexSubImage2D( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLint x, GLint y, GLsizei width, - GLsizei height); -void glCullFace(GLenum mode); -void glDeleteTextures(GLsizei n, const GLuint *textures); -void glDepthFunc(GLenum func); -void glDepthMask(GLboolean flag); -void glDepthRangef(GLclampf zNear, GLclampf zFar); -void glDepthRangex(GLclampx zNear, GLclampx zFar); -void glDisable(GLenum cap); -void glDisableClientState(GLenum array); -void glDrawArrays(GLenum mode, GLint first, GLsizei count); -void glDrawElements(GLenum mode, GLsizei count, - GLenum type, const GLvoid *indices); -void glEnable(GLenum cap); -void glEnableClientState(GLenum array); -void glFinish(void); -void glFlush(void); -void glFogf(GLenum pname, GLfloat param); -void glFogfv(GLenum pname, const GLfloat *params); -void glFogx(GLenum pname, GLfixed param); -void glFogxv(GLenum pname, const GLfixed *params); -void glFrontFace(GLenum mode); -void glFrustumf(GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat zNear, GLfloat zFar); -void glFrustumx(GLfixed left, GLfixed right, - GLfixed bottom, GLfixed top, - GLfixed zNear, GLfixed zFar); -void glGenTextures(GLsizei n, GLuint *textures); -GLenum glGetError(void); -void glGetIntegerv(GLenum pname, GLint *params); -const GLubyte * glGetString(GLenum name); -void glHint(GLenum target, GLenum mode); -void glLightModelf(GLenum pname, GLfloat param); -void glLightModelfv(GLenum pname, const GLfloat *params); -void glLightModelx(GLenum pname, GLfixed param); -void glLightModelxv(GLenum pname, const GLfixed *params); -void glLightf(GLenum light, GLenum pname, GLfloat param); -void glLightfv(GLenum light, GLenum pname, const GLfloat *params); -void glLightx(GLenum light, GLenum pname, GLfixed param); -void glLightxv(GLenum light, GLenum pname, const GLfixed *params); -void glLineWidth(GLfloat width); -void glLineWidthx(GLfixed width); -void glLoadIdentity(void); -void glLoadMatrixf(const GLfloat *m); -void glLoadMatrixx(const GLfixed *m); -void glLogicOp(GLenum opcode); -void glMaterialf(GLenum face, GLenum pname, GLfloat param); -void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params); -void glMaterialx(GLenum face, GLenum pname, GLfixed param); -void glMaterialxv(GLenum face, GLenum pname, const GLfixed *params); -void glMatrixMode(GLenum mode); -void glMultMatrixf(const GLfloat *m); -void glMultMatrixx(const GLfixed *m); -void glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); -void glMultiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q); -void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz); -void glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz); -void glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer); -void glOrthof( GLfloat left, GLfloat right, - GLfloat bottom, GLfloat top, - GLfloat zNear, GLfloat zFar); -void glOrthox( GLfixed left, GLfixed right, - GLfixed bottom, GLfixed top, - GLfixed zNear, GLfixed zFar); -void glPixelStorei(GLenum pname, GLint param); -void glPointSize(GLfloat size); -void glPointSizex(GLfixed size); -void glPolygonOffset(GLfloat factor, GLfloat units); -void glPolygonOffsetx(GLfixed factor, GLfixed units); -void glPopMatrix(void); -void glPushMatrix(void); -void glReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid *pixels); -void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -void glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z); -void glSampleCoverage(GLclampf value, GLboolean invert); -void glSampleCoveragex(GLclampx value, GLboolean invert); -void glScalef(GLfloat x, GLfloat y, GLfloat z); -void glScalex(GLfixed x, GLfixed y, GLfixed z); -void glScissor(GLint x, GLint y, GLsizei width, GLsizei height); -void glShadeModel(GLenum mode); -void glStencilFunc(GLenum func, GLint ref, GLuint mask); -void glStencilMask(GLuint mask); -void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass); -void glTexCoordPointer( GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer); -void glTexEnvf(GLenum target, GLenum pname, GLfloat param); -void glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params); -void glTexEnvx(GLenum target, GLenum pname, GLfixed param); -void glTexEnvxv(GLenum target, GLenum pname, const GLfixed *params); -void glTexImage2D( GLenum target, GLint level, GLenum internalformat, - GLsizei width, GLsizei height, GLint border, GLenum format, - GLenum type, const GLvoid *pixels); -void glTexParameterf(GLenum target, GLenum pname, GLfloat param); -void glTexParameterx(GLenum target, GLenum pname, GLfixed param); -void glTexSubImage2D( GLenum target, GLint level, GLint xoffset, - GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid *pixels); -void glTranslatef(GLfloat x, GLfloat y, GLfloat z); -void glTranslatex(GLfixed x, GLfixed y, GLfixed z); -void glVertexPointer( GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer); -void glViewport(GLint x, GLint y, GLsizei width, GLsizei height); - -/*****************************************************************************/ -/* OpenGL ES 1.1 functions */ - -void glClipPlanef(GLenum plane, const GLfloat* equation); -void glClipPlanex(GLenum plane, const GLfixed* equation); - -void glBindBuffer(GLenum target, GLuint buffer); -void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); -void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); -void glDeleteBuffers(GLsizei n, const GLuint* buffers); -void glGenBuffers(GLsizei n, GLuint* buffers); - -void glGetBooleanv(GLenum pname, GLboolean *params); -void glGetFixedv(GLenum pname, GLfixed *params); -void glGetFloatv(GLenum pname, GLfloat *params); -void glGetPointerv(GLenum pname, void **params); -void glGetBufferParameteriv(GLenum target, GLenum pname, GLint *params); -void glGetClipPlanef(GLenum pname, GLfloat eqn[4]); -void glGetClipPlanex(GLenum pname, GLfixed eqn[4]); -void glGetLightxv(GLenum light, GLenum pname, GLfixed *params); -void glGetLightfv(GLenum light, GLenum pname, GLfloat *params); -void glGetMaterialxv(GLenum face, GLenum pname, GLfixed *params); -void glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params); -void glGetTexEnvfv(GLenum env, GLenum pname, GLfloat *params); -void glGetTexEnviv(GLenum env, GLenum pname, GLint *params); -void glGetTexEnvxv(GLenum env, GLenum pname, GLfixed *params); -void glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params); -void glGetTexParameteriv(GLenum target, GLenum pname, GLint *params); -void glGetTexParameterxv(GLenum target, GLenum pname, GLfixed *params); -GLboolean glIsBuffer(GLuint buffer); -GLboolean glIsEnabled(GLenum cap); -GLboolean glIsTexture(GLuint texture); -void glPointParameterf(GLenum pname, GLfloat param); -void glPointParameterfv(GLenum pname, const GLfloat *params); -void glPointParameterx(GLenum pname, GLfixed param); -void glPointParameterxv(GLenum pname, const GLfixed *params); -void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -void glTexEnvi(GLenum target, GLenum pname, GLint param); -void glTexEnviv(GLenum target, GLenum pname, const GLint *params); -void glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params); -void glTexParameteriv(GLenum target, GLenum pname, const GLint *params); -void glTexParameteri(GLenum target, GLenum pname, GLint param); -void glTexParameterxv(GLenum target, GLenum pname, const GLfixed *params); - -/*****************************************************************************/ -/* Required extensions functions */ - -void glPointSizePointerOES(GLenum type, GLsizei stride, const GLvoid *pointer); - - -/*****************************************************************************/ -/* Extensions functions */ - -void glDrawTexsOES(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h); -void glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h); -void glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h); -void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h); -void glDrawTexsvOES(const GLshort* coords); -void glDrawTexivOES(const GLint* coords); -void glDrawTexfvOES(const GLfloat* coords); -void glDrawTexxvOES(const GLfixed* coords); -GLbitfield glQueryMatrixxOES(GLfixed* mantissa, GLint* exponent); - -/* called by dalvik */ -void glColorPointerBounds(GLint size, GLenum type, GLsizei stride, - const GLvoid *ptr, GLsizei count); -void glNormalPointerBounds(GLenum type, GLsizei stride, - const GLvoid *pointer, GLsizei count); -void glTexCoordPointerBounds(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer, GLsizei count); -void glVertexPointerBounds(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer, GLsizei count); - -#ifdef __cplusplus -} -#endif - -#endif /* __gl_h_ */ diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h index 3056139bef..0c7ad462fb 100644 --- a/include/private/opengles/gl_context.h +++ b/include/private/opengles/gl_context.h @@ -28,6 +28,7 @@ #include <private/pixelflinger/ggl_context.h> #include <GLES/gl.h> +#include <GLES/glext.h> namespace android { diff --git a/include/ui/Camera.h b/include/ui/Camera.h index 44acce5dd0..e593feab78 100644 --- a/include/ui/Camera.h +++ b/include/ui/Camera.h @@ -23,8 +23,8 @@ namespace android { /* - * A set of bit masks for specifying how the received frames from preview are - * handled before the frame callback call. + * A set of bit masks for specifying how the received preview frames are + * handled before the previewCallback() call. * * The least significant 3 bits of an "int" value are used for this purpose: * @@ -34,10 +34,18 @@ namespace android { * | |-----------> determine whether the callback is one-shot or not * |-------------> determine whether the frame is copied out or not * + * WARNING: + * When a frame is sent directly without copying, it is the frame receiver's + * responsiblity to make sure that the frame data won't get corrupted by + * subsequent preview frames filled by the camera. This flag is recommended + * only when copying out data brings significant performance price and the + * handling/processing of the received frame data is always faster than + * the preview frame rate so that data corruption won't occur. + * * For instance, * 1. 0x00 disables the callback. In this case, copy out and one shot bits * are ignored. - * 2. 0x01 enables a callback without copying out the recievied frames. A + * 2. 0x01 enables a callback without copying out the received frames. A * typical use case is the Camcorder application to avoid making costly * frame copies. * 3. 0x05 is enabling a callback with frame copied out repeatedly. A typical @@ -96,6 +104,18 @@ public: // get preview state bool previewEnabled(); + // start recording mode, must call setPreviewDisplay first + status_t startRecording(); + + // stop recording mode + void stopRecording(); + + // get recording state + bool recordingEnabled(); + + // release a recording frame + void releaseRecordingFrame(const sp<IMemory>& mem); + // autoFocus - status returned from callback status_t autoFocus(); @@ -111,20 +131,19 @@ public: void setShutterCallback(shutter_callback cb, void *cookie); void setRawCallback(frame_callback cb, void *cookie); void setJpegCallback(frame_callback cb, void *cookie); - - void setFrameCallback(frame_callback cb, - void *cookie, - int frame_callback_flag = FRAME_CALLBACK_FLAG_NOOP); - + void setRecordingCallback(frame_callback cb, void *cookie); + void setPreviewCallback(frame_callback cb, void *cookie, int preview_callback_flag = FRAME_CALLBACK_FLAG_NOOP); void setErrorCallback(error_callback cb, void *cookie); void setAutoFocusCallback(autofocus_callback cb, void *cookie); + // ICameraClient interface virtual void shutterCallback(); virtual void rawCallback(const sp<IMemory>& picture); virtual void jpegCallback(const sp<IMemory>& picture); - virtual void frameCallback(const sp<IMemory>& frame); + virtual void previewCallback(const sp<IMemory>& frame); virtual void errorCallback(status_t error); virtual void autoFocusCallback(bool focused); + virtual void recordingCallback(const sp<IMemory>& frame); sp<ICamera> remote(); @@ -155,8 +174,10 @@ private: void *mRawCallbackCookie; frame_callback mJpegCallback; void *mJpegCallbackCookie; - frame_callback mFrameCallback; - void *mFrameCallbackCookie; + frame_callback mPreviewCallback; + void *mPreviewCallbackCookie; + frame_callback mRecordingCallback; + void *mRecordingCallbackCookie; error_callback mErrorCallback; void *mErrorCallbackCookie; autofocus_callback mAutoFocusCallback; diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h index 2bd53dde32..73036f0fa7 100644 --- a/include/ui/CameraHardwareInterface.h +++ b/include/ui/CameraHardwareInterface.h @@ -20,12 +20,16 @@ #include <utils/IMemory.h> #include <utils/RefBase.h> #include <ui/CameraParameters.h> +#include <ui/Overlay.h> namespace android { /** Callback for startPreview() */ typedef void (*preview_callback)(const sp<IMemory>& mem, void* user); +/** Callback for startRecord() */ +typedef void (*recording_callback)(const sp<IMemory>& mem, void* user); + /** Callback for takePicture() */ typedef void (*shutter_callback)(void* user); @@ -83,12 +87,20 @@ public: /** Return the IMemoryHeap for the preview image heap */ virtual sp<IMemoryHeap> getPreviewHeap() const = 0; + /** Return the IMemoryHeap for the raw image heap */ + virtual sp<IMemoryHeap> getRawHeap() const = 0; + /** * Start preview mode. When a preview image is available * preview_callback is called with the user parameter. The * call back parameter may be null. */ virtual status_t startPreview(preview_callback cb, void* user) = 0; + /** + * Only used if overlays are used for camera preview. + */ + virtual bool useOverlay() {return false;} + virtual status_t setOverlay(const sp<Overlay> &overlay) {return BAD_VALUE;} /** * Stop a previously started preview. @@ -101,6 +113,29 @@ public: virtual bool previewEnabled() = 0; /** + * Start record mode. When a record image is available recording_callback() + * is called with the user parameter. Every record frame must be released + * by calling releaseRecordingFrame(). + */ + virtual status_t startRecording(recording_callback cb, void* user) = 0; + + /** + * Stop a previously started recording. + */ + virtual void stopRecording() = 0; + + /** + * Returns true if recording is enabled. + */ + virtual bool recordingEnabled() = 0; + + /** + * Release a record frame previously returned by the recording_callback() + * passed to startRecord(). + */ + virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0; + + /** * Start auto focus, the callback routine is called * once when focusing is complete. autoFocus() will * be called again if another auto focus is needed. diff --git a/include/ui/CameraParameters.h b/include/ui/CameraParameters.h index e35a0546ba..9ca18068ef 100644 --- a/include/ui/CameraParameters.h +++ b/include/ui/CameraParameters.h @@ -29,6 +29,12 @@ public: CameraParameters(const String8 ¶ms) { unflatten(params); } ~CameraParameters(); + enum { + CAMERA_ORIENTATION_UNKNOWN = 0, + CAMERA_ORIENTATION_PORTRAIT = 1, + CAMERA_ORIENTATION_LANDSCAPE = 2, + }; + String8 flatten() const; void unflatten(const String8 ¶ms); @@ -57,6 +63,9 @@ public: void setPictureFormat(const char *format); const char *getPictureFormat() const; + int getOrientation() const; + void setOrientation(int orientation); + void dump() const; status_t dump(int fd, const Vector<String16>& args) const; diff --git a/include/ui/EGLDisplaySurface.h b/include/ui/EGLDisplaySurface.h index 0190e09979..a8b58539d1 100644 --- a/include/ui/EGLDisplaySurface.h +++ b/include/ui/EGLDisplaySurface.h @@ -27,7 +27,10 @@ #include <pixelflinger/pixelflinger.h> #include <linux/fb.h> +#include <EGL/egl.h> + struct copybit_device_t; +struct copybit_image_t; // --------------------------------------------------------------------------- namespace android { @@ -44,17 +47,17 @@ public: int32_t getPageFlipCount() const; void copyFrontToBack(const Region& copyback); + void copyFrontToImage(const copybit_image_t& dst); + void copyBackToImage(const copybit_image_t& dst); + void setSwapRectangle(int l, int t, int w, int h); + private: static void hook_incRef(NativeWindowType window); static void hook_decRef(NativeWindowType window); static uint32_t hook_swapBuffers(NativeWindowType window); - static void hook_setSwapRectangle(NativeWindowType window, int l, int t, int w, int h); - static uint32_t hook_nextBuffer(NativeWindowType window); uint32_t swapBuffers(); - uint32_t nextBuffer(); - void setSwapRectangle(int l, int t, int w, int h); status_t mapFrameBuffer(); diff --git a/include/ui/EGLNativeSurface.h b/include/ui/EGLNativeSurface.h index c303cd8d4a..7964e7c6ba 100644 --- a/include/ui/EGLNativeSurface.h +++ b/include/ui/EGLNativeSurface.h @@ -23,7 +23,7 @@ #include <cutils/atomic.h> #include <utils/RefBase.h> -#include <GLES/eglnatives.h> +#include <EGL/eglnatives.h> // --------------------------------------------------------------------------- namespace android { diff --git a/include/ui/EGLNativeWindowSurface.h b/include/ui/EGLNativeWindowSurface.h index 058479a2a6..3494234636 100644 --- a/include/ui/EGLNativeWindowSurface.h +++ b/include/ui/EGLNativeWindowSurface.h @@ -20,6 +20,7 @@ #include <stdint.h> #include <sys/types.h> #include <ui/EGLNativeSurface.h> +#include <EGL/egl.h> // --------------------------------------------------------------------------- namespace android { @@ -33,18 +34,16 @@ public: EGLNativeWindowSurface(const sp<Surface>& surface); ~EGLNativeWindowSurface(); + void setSwapRectangle(int l, int t, int w, int h); + private: static void hook_incRef(NativeWindowType window); static void hook_decRef(NativeWindowType window); static uint32_t hook_swapBuffers(NativeWindowType window); - static uint32_t hook_nextBuffer(NativeWindowType window); - static void hook_setSwapRectangle(NativeWindowType window, int l, int t, int w, int h); static void hook_connect(NativeWindowType window); static void hook_disconnect(NativeWindowType window); uint32_t swapBuffers(); - uint32_t nextBuffer(); - void setSwapRectangle(int l, int t, int w, int h); void connect(); void disconnect(); diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h index 017c145bfb..3848d8c3bd 100644 --- a/include/ui/EventHub.h +++ b/include/ui/EventHub.h @@ -76,6 +76,9 @@ public: DEVICE_REMOVED = 0x20000000 }; + // examine key input devices for specific framework keycode support + bool hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags); + virtual bool getEvent(int32_t* outDeviceId, int32_t* outType, int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags, int32_t* outValue, nsecs_t* outWhen); @@ -100,6 +103,7 @@ private: const String8 path; String8 name; uint32_t classes; + uint8_t* keyBitmask; KeyLayoutMap* layoutMap; String8 keylayoutFilename; device_t* next; @@ -134,8 +138,6 @@ private: #ifdef EV_SW int32_t mSwitches[SW_MAX+1]; #endif - - KeyLayoutMap * mLayoutMap; }; }; // namespace android diff --git a/include/ui/ICamera.h b/include/ui/ICamera.h index ea2fcee2ae..241fb63261 100644 --- a/include/ui/ICamera.h +++ b/include/ui/ICamera.h @@ -48,9 +48,9 @@ public: // pass the buffered ISurface to the camera service virtual status_t setPreviewDisplay(const sp<ISurface>& surface) = 0; - // set the frame callback flag to affect how the received frames from + // set the preview callback flag to affect how the received frames from // preview are handled. - virtual void setFrameCallbackFlag(int frame_callback_flag) = 0; + virtual void setPreviewCallbackFlag(int flag) = 0; // start preview mode, must call setPreviewDisplay first virtual status_t startPreview() = 0; @@ -61,6 +61,18 @@ public: // get preview state virtual bool previewEnabled() = 0; + // start recording mode + virtual status_t startRecording() = 0; + + // stop recording mode + virtual void stopRecording() = 0; + + // get recording state + virtual bool recordingEnabled() = 0; + + // release a recording frame + virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0; + // auto focus virtual status_t autoFocus() = 0; diff --git a/include/ui/ICameraClient.h b/include/ui/ICameraClient.h index a286b8e0a5..73b951cf3c 100644 --- a/include/ui/ICameraClient.h +++ b/include/ui/ICameraClient.h @@ -32,9 +32,10 @@ public: virtual void shutterCallback() = 0; virtual void rawCallback(const sp<IMemory>& picture) = 0; virtual void jpegCallback(const sp<IMemory>& picture) = 0; - virtual void frameCallback(const sp<IMemory>& frame) = 0; + virtual void previewCallback(const sp<IMemory>& frame) = 0; virtual void errorCallback(status_t error) = 0; virtual void autoFocusCallback(bool focused) = 0; + virtual void recordingCallback(const sp<IMemory>& frame) = 0; }; diff --git a/include/ui/ICameraService.h b/include/ui/ICameraService.h index dfd8923001..c652c5169a 100644 --- a/include/ui/ICameraService.h +++ b/include/ui/ICameraService.h @@ -28,7 +28,7 @@ namespace android { class ICameraService : public IInterface { -protected: +public: enum { CONNECT = IBinder::FIRST_CALL_TRANSACTION, }; diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h index 9a7383cc24..87b320f431 100644 --- a/include/ui/ISurface.h +++ b/include/ui/ISurface.h @@ -25,6 +25,8 @@ #include <utils/RefBase.h> #include <ui/PixelFormat.h> +#include <hardware/hardware.h> + namespace android { typedef int32_t SurfaceID; @@ -34,11 +36,48 @@ class OverlayRef; class ISurface : public IInterface { +protected: + enum { + REGISTER_BUFFERS = IBinder::FIRST_CALL_TRANSACTION, + UNREGISTER_BUFFERS, + POST_BUFFER, // one-way transaction + CREATE_OVERLAY, + }; + public: DECLARE_META_INTERFACE(Surface); - virtual status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap) = 0; + + class BufferHeap { + public: + enum { + /* rotate source image 90 degrees */ + ROT_90 = HAL_TRANSFORM_ROT_90, + }; + BufferHeap(); + + BufferHeap(uint32_t w, uint32_t h, + int32_t hor_stride, int32_t ver_stride, + PixelFormat format, const sp<IMemoryHeap>& heap); + + BufferHeap(uint32_t w, uint32_t h, + int32_t hor_stride, int32_t ver_stride, + PixelFormat format, uint32_t transform, uint32_t flags, + const sp<IMemoryHeap>& heap); + + ~BufferHeap(); + + uint32_t w; + uint32_t h; + int32_t hor_stride; + int32_t ver_stride; + PixelFormat format; + uint32_t transform; + uint32_t flags; + sp<IMemoryHeap> heap; + }; + + virtual status_t registerBuffers(const BufferHeap& buffers) = 0; virtual void postBuffer(ssize_t offset) = 0; // one-way diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h index 53c1188728..efa6d2bdd3 100644 --- a/include/ui/KeycodeLabels.h +++ b/include/ui/KeycodeLabels.h @@ -113,6 +113,7 @@ static const KeycodeLabel KEYCODES[] = { { "PREVIOUSSONG", 88 }, { "REWIND", 89 }, { "FORWARD", 90 }, + { "MUTE", 91 }, // NOTE: If you add a new keycode here you must also add it to: // (enum KeyCode, in this file) @@ -216,7 +217,8 @@ typedef enum KeyCode { kKeyCodeNextSong = 87, kKeyCodePreviousSong = 88, kKeyCodeRewind = 89, - kKeyCodeForward = 90 + kKeyCodeForward = 90, + kKeyCodeMute = 91 } KeyCode; static const KeycodeLabel FLAGS[] = { diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h index b65c959261..14af8232bb 100644 --- a/include/ui/PixelFormat.h +++ b/include/ui/PixelFormat.h @@ -71,6 +71,10 @@ enum { PIXEL_FORMAT_YCbCr_422_SP= GGL_PIXEL_FORMAT_YCbCr_422_SP, PIXEL_FORMAT_YCbCr_420_SP= GGL_PIXEL_FORMAT_YCbCr_420_SP, + PIXEL_FORMAT_YCbCr_422_P = GGL_PIXEL_FORMAT_YCbCr_422_P, + PIXEL_FORMAT_YCbCr_420_P = GGL_PIXEL_FORMAT_YCbCr_420_P, + PIXEL_FORMAT_YCbCr_422_I = GGL_PIXEL_FORMAT_YCbCr_422_I, + PIXEL_FORMAT_YCbCr_420_I = GGL_PIXEL_FORMAT_YCbCr_420_I, // New formats can be added if they're also defined in // pixelflinger/format.h @@ -80,7 +84,19 @@ typedef int32_t PixelFormat; struct PixelFormatInfo { + enum { // components + ALPHA = 1, + RGB = 2, + RGBA = 3, + LUMINANCE = 4, + LUMINANCE_ALPHA = 5, + Y_CB_CR_SP = 6, + Y_CB_CR_P = 7, + Y_CB_CR_I = 8, + }; + inline PixelFormatInfo() : version(sizeof(PixelFormatInfo)) { } + size_t getScanlineSize(unsigned int width) const; size_t version; PixelFormat format; size_t bytesPerPixel; @@ -93,7 +109,9 @@ struct PixelFormatInfo uint8_t l_green; uint8_t h_blue; uint8_t l_blue; - uint32_t reserved[2]; + uint8_t components; + uint8_t reserved0[3]; + uint32_t reserved1; }; // Consider caching the results of these functions are they're not diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h index 2d56e3e263..7d3fcf2a83 100644 --- a/include/utils/ResourceTypes.h +++ b/include/utils/ResourceTypes.h @@ -223,7 +223,7 @@ struct Res_value { // Number of bytes in this structure. uint16_t size; - + // Always set to 0. uint8_t res0; @@ -1101,16 +1101,22 @@ struct ResTable_config return false; } - // Return true if 'this' can be considered a match for the parameters in + // Return true if 'this' can be considered a match for the parameters in // 'settings'. + // Note this is asymetric. A default piece of data will match every request + // but a request for the default should not match odd specifics + // (ie, request with no mcc should not match a particular mcc's data) + // settings is the requested settings inline bool match(const ResTable_config& settings) const { if (imsi != 0) { - if (settings.mcc != 0 && mcc != 0 - && mcc != settings.mcc) { + if ((settings.mcc != 0 && mcc != 0 + && mcc != settings.mcc) || + (settings.mcc == 0 && mcc != 0)) { return false; } - if (settings.mnc != 0 && mnc != 0 - && mnc != settings.mnc) { + if ((settings.mnc != 0 && mnc != 0 + && mnc != settings.mnc) || + (settings.mnc == 0 && mnc != 0)) { return false; } } @@ -1131,10 +1137,8 @@ struct ResTable_config && orientation != settings.orientation) { return false; } - if (settings.density != 0 && density != 0 - && density != settings.density) { - return false; - } + // Density not taken into account, always match, no matter what + // density is specified for the resource if (settings.touchscreen != 0 && touchscreen != 0 && touchscreen != settings.touchscreen) { return false; @@ -1464,11 +1468,11 @@ public: * @return ssize_t Either a >= 0 table index or a negative error code. */ ssize_t getResource(uint32_t resID, Res_value* outValue, bool mayBeBag=false, - uint32_t* outSpecFlags=NULL) const; + uint32_t* outSpecFlags=NULL, ResTable_config* outConfig=NULL) const; inline ssize_t getResource(const ResTable_ref& res, Res_value* outValue, uint32_t* outSpecFlags=NULL) const { - return getResource(res.ident, outValue, outSpecFlags); + return getResource(res.ident, outValue, false, outSpecFlags, NULL); } ssize_t resolveReference(Res_value* inOutValue, diff --git a/include/utils/logger.h b/include/utils/logger.h deleted file mode 100644 index 3a08019a88..0000000000 --- a/include/utils/logger.h +++ /dev/null @@ -1,46 +0,0 @@ -/* utils/logger.h -** -** Copyright 2007, The Android Open Source Project -** -** This file is dual licensed. It may be redistributed and/or modified -** under the terms of the Apache 2.0 License OR version 2 of the GNU -** General Public License. -*/ - -#ifndef _UTILS_LOGGER_H -#define _UTILS_LOGGER_H - -#include <stdint.h> - -struct logger_entry { - uint16_t len; /* length of the payload */ - uint16_t __pad; /* no matter what, we get 2 bytes of padding */ - int32_t pid; /* generating process's pid */ - int32_t tid; /* generating process's tid */ - int32_t sec; /* seconds since Epoch */ - int32_t nsec; /* nanoseconds */ - char msg[0]; /* the entry's payload */ -}; - -#define LOGGER_LOG_MAIN "log/main" -#define LOGGER_LOG_RADIO "log/radio" -#define LOGGER_LOG_EVENTS "log/events" - -#define LOGGER_ENTRY_MAX_LEN (4*1024) -#define LOGGER_ENTRY_MAX_PAYLOAD \ - (LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry)) - -#ifdef HAVE_IOCTL - -#include <sys/ioctl.h> - -#define __LOGGERIO 0xAE - -#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */ -#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */ -#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */ -#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */ - -#endif // HAVE_IOCTL - -#endif /* _UTILS_LOGGER_H */ diff --git a/include/utils/threads.h b/include/utils/threads.h index 7dca810043..8d8d46a054 100644 --- a/include/utils/threads.h +++ b/include/utils/threads.h @@ -249,41 +249,6 @@ private: /* - * Read/write lock. The resource can have multiple readers or one writer, - * but can't be read and written at the same time. - * - * The same thread should not call a lock function while it already has - * a lock. (Should be okay for multiple readers.) - */ -class ReadWriteLock { -public: - ReadWriteLock() - : mNumReaders(0), mNumWriters(0) - {} - ~ReadWriteLock() {} - - void lockForRead(); - bool tryLockForRead(); - void unlockForRead(); - - void lockForWrite(); - bool tryLockForWrite(); - void unlockForWrite(); - -private: - int mNumReaders; - int mNumWriters; - - Mutex mLock; - Condition mReadWaiter; - Condition mWriteWaiter; -#if defined(PRINT_RENDER_TIMES) - DurationTimer mDebugTimer; -#endif -}; - - -/* * This is our spiffy thread object! */ diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp index c8c8431096..2974e32ee1 100644 --- a/libs/audioflinger/A2dpAudioInterface.cpp +++ b/libs/audioflinger/A2dpAudioInterface.cpp @@ -48,7 +48,6 @@ AudioStreamOut* A2dpAudioInterface::openOutputStream( int format, int channelCount, uint32_t sampleRate, status_t *status) { LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate); - Mutex::Autolock lock(mLock); status_t err = 0; // only one output stream allowed @@ -72,7 +71,8 @@ AudioStreamOut* A2dpAudioInterface::openOutputStream( } AudioStreamIn* A2dpAudioInterface::openInputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) + int format, int channelCount, uint32_t sampleRate, status_t *status, + AudioSystem::audio_in_acoustics acoustics) { if (status) *status = -1; @@ -99,6 +99,10 @@ status_t A2dpAudioInterface::setParameter(const char *key, const char *value) if (strcmp(key, "a2dp_sink_address") == 0) { return mOutput->setAddress(value); } + if (strcmp(key, "bluetooth_enabled") == 0 && + strcmp(value, "false") == 0) { + return mOutput->close(); + } return 0; } @@ -126,11 +130,11 @@ status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args) // ---------------------------------------------------------------------------- A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() : - mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL), - mInitialized(false) + mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL) { // use any address by default - strncpy(mA2dpAddress, "00:00:00:00:00:00", sizeof(mA2dpAddress)); + strcpy(mA2dpAddress, "00:00:00:00:00:00"); + init(); } status_t A2dpAudioInterface::A2dpAudioStreamOut::set( @@ -154,23 +158,17 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::set( A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut() { - if (mData) - a2dp_cleanup(mData); + close(); } ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes) { - status_t status = NO_INIT; - size_t remaining = bytes; + Mutex::Autolock lock(mLock); - if (!mInitialized) { - status = a2dp_init(mA2dpAddress, 44100, 2, &mData); - if (status < 0) { - LOGE("a2dp_init failed err: %d\n", status); - goto Error; - } - mInitialized = true; - } + size_t remaining = bytes; + status_t status = init(); + if (status < 0) + goto Error; while (remaining > 0) { status = a2dp_write(mData, buffer, remaining); @@ -186,17 +184,34 @@ ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t return bytes; -Error: +Error: // Simulate audio output timing in case of error usleep(bytes * 1000000 / frameSize() / sampleRate()); return status; } +status_t A2dpAudioInterface::A2dpAudioStreamOut::init() +{ + if (!mData) { + status_t status = a2dp_init(44100, 2, &mData); + if (status < 0) { + LOGE("a2dp_init failed err: %d\n", status); + mData = NULL; + return status; + } + a2dp_set_sink(mData, mA2dpAddress); + } + + return 0; +} + status_t A2dpAudioInterface::A2dpAudioStreamOut::standby() { int result = 0; + Mutex::Autolock lock(mLock); + if (!mStandby) { result = a2dp_stop(mData); if (result == 0) @@ -208,19 +223,24 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::standby() status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address) { - if (strlen(address) < sizeof(mA2dpAddress)) + Mutex::Autolock lock(mLock); + + if (strlen(address) != strlen("00:00:00:00:00:00")) return -EINVAL; - if (strcmp(address, mA2dpAddress)) { - strcpy(mA2dpAddress, address); - - if (mInitialized) { - a2dp_cleanup(mData); - mData = NULL; - mInitialized = false; - } + strcpy(mA2dpAddress, address); + if (mData) + a2dp_set_sink(mData, mA2dpAddress); + + return NO_ERROR; +} + +status_t A2dpAudioInterface::A2dpAudioStreamOut::close() +{ + if (mData) { + a2dp_cleanup(mData); + mData = NULL; } - return NO_ERROR; } diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h index 2197d0eb5b..99614dc108 100644 --- a/libs/audioflinger/A2dpAudioInterface.h +++ b/libs/audioflinger/A2dpAudioInterface.h @@ -58,7 +58,8 @@ public: int format, int channelCount, uint32_t sampleRate, - status_t *status); + status_t *status, + AudioSystem::audio_in_acoustics acoustics); protected: virtual status_t doRouting(); @@ -77,7 +78,7 @@ private: virtual size_t bufferSize() const { return 512 * 20; } virtual int channelCount() const { return 2; } virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return ((1000*channelCount()*bufferSize())/frameSize())/sampleRate() + 200; } + virtual uint32_t latency() const { return ((1000*bufferSize())/frameSize())/sampleRate() + 200; } virtual status_t setVolume(float volume) { return INVALID_OPERATION; } virtual ssize_t write(const void* buffer, size_t bytes); status_t standby(); @@ -85,6 +86,8 @@ private: private: friend class A2dpAudioInterface; + status_t init(); + status_t close(); status_t setAddress(const char* address); private: @@ -94,10 +97,9 @@ private: int mRetryCount; char mA2dpAddress[20]; void* mData; - bool mInitialized; + Mutex mLock; }; - Mutex mLock; A2dpAudioStreamOut* mOutput; }; diff --git a/libs/audioflinger/AudioDumpInterface.h b/libs/audioflinger/AudioDumpInterface.h index 42204d6334..9a941021e6 100644 --- a/libs/audioflinger/AudioDumpInterface.h +++ b/libs/audioflinger/AudioDumpInterface.h @@ -78,8 +78,9 @@ public: virtual status_t setParameter(const char* key, const char* value) {return mFinalInterface->setParameter(key, value);} - virtual AudioStreamIn* openInputStream( int format, int channelCount, uint32_t sampleRate, status_t *status) - {return mFinalInterface->openInputStream( format, channelCount, sampleRate, status);} + virtual AudioStreamIn* openInputStream( int format, int channelCount, uint32_t sampleRate, status_t *status, + AudioSystem::audio_in_acoustics acoustics) + {return mFinalInterface->openInputStream( format, channelCount, sampleRate, status, acoustics);} virtual status_t dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); } diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 918b01fea9..3c81a47812 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -47,6 +47,15 @@ #include "A2dpAudioInterface.h" #endif +// ---------------------------------------------------------------------------- +// the sim build doesn't have gettid + +#ifndef HAVE_GETTID +# define gettid getpid +#endif + +// ---------------------------------------------------------------------------- + namespace android { //static const nsecs_t kStandbyTimeInNsecs = seconds(3); @@ -59,6 +68,16 @@ static const float MAX_GAIN = 4096.0f; static const int8_t kMaxTrackRetries = 50; static const int8_t kMaxTrackStartupRetries = 50; +static const int kStartSleepTime = 30000; +static const int kStopSleepTime = 30000; + +static const int kDumpLockRetries = 50; +static const int kDumpLockSleep = 20000; + +// Maximum number of pending buffers allocated by OutputTrack::write() +static const uint8_t kMaxOutputTrackBuffers = 5; + + #define AUDIOFLINGER_SECURITY_ENABLED 1 // ---------------------------------------------------------------------------- @@ -98,13 +117,10 @@ static bool settingsAllowed() { // ---------------------------------------------------------------------------- AudioFlinger::AudioFlinger() - : BnAudioFlinger(), Thread(false), - mMasterVolume(0), mMasterMute(true), mHardwareAudioMixer(0), mA2dpAudioMixer(0), - mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0), mHardwareOutput(0), - mA2dpOutput(0), mOutput(0), mRequestedOutput(0), mAudioRecordThread(0), - mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0), - mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false), - mInWrite(false), mA2dpDisableCount(0), mA2dpSuppressed(false) + : BnAudioFlinger(), + mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false), + mForcedSpeakerCount(0), mA2dpDisableCount(0), mA2dpSuppressed(false), mForcedRoute(0), + mRouteRestoreTime(0), mMusicMuteSaved(false) { mHardwareStatus = AUDIO_HW_IDLE; mAudioHardware = AudioHardwareInterface::create(); @@ -113,57 +129,51 @@ AudioFlinger::AudioFlinger() // open 16-bit output stream for s/w mixer mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; status_t status; - mHardwareOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); + AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); mHardwareStatus = AUDIO_HW_IDLE; - if (mHardwareOutput) { - mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mHardwareOutput->sampleRate()); - mRequestedOutput = mHardwareOutput; - doSetOutput(mHardwareOutput); - - // FIXME - this should come from settings - setMasterVolume(1.0f); - setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); - setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); - setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL); - setMode(AudioSystem::MODE_NORMAL); - mMasterMute = false; + if (hwOutput) { + mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE); } else { - LOGE("Failed to initialize output stream, status: %d", status); + LOGE("Failed to initialize hardware output stream, status: %d", status); } #ifdef WITH_A2DP // Create A2DP interface mA2dpAudioInterface = new A2dpAudioInterface(); - mA2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); - mA2dpAudioMixer = new AudioMixer(getOutputFrameCount(mA2dpOutput), mA2dpOutput->sampleRate()); - - // create a buffer big enough for both hardware and A2DP audio output. - size_t hwFrameCount = getOutputFrameCount(mHardwareOutput); - size_t a2dpFrameCount = getOutputFrameCount(mA2dpOutput); - size_t frameCount = (hwFrameCount > a2dpFrameCount ? hwFrameCount : a2dpFrameCount); -#else - size_t frameCount = getOutputFrameCount(mHardwareOutput); + AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status); + if (a2dpOutput) { + mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP); + if (hwOutput) { + uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate(); + MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread, + hwOutput->sampleRate(), + AudioSystem::PCM_16_BIT, + hwOutput->channelCount(), + frameCount); + mHardwareMixerThread->setOuputTrack(a2dpOutTrack); + } + } else { + LOGE("Failed to initialize A2DP output stream, status: %d", status); + } #endif - // FIXME - Current mixer implementation only supports stereo output: Always - // Allocate a stereo buffer even if HW output is mono. - mMixBuffer = new int16_t[frameCount * 2]; - memset(mMixBuffer, 0, frameCount * 2 * sizeof(int16_t)); - + + // FIXME - this should come from settings + setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); + setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); + setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL); + setMode(AudioSystem::MODE_NORMAL); + + setMasterVolume(1.0f); + setMasterMute(false); + // Start record thread - mAudioRecordThread = new AudioRecordThread(mAudioHardware); + mAudioRecordThread = new AudioRecordThread(mAudioHardware, this); if (mAudioRecordThread != 0) { mAudioRecordThread->run("AudioRecordThread", PRIORITY_URGENT_AUDIO); } } else { LOGE("Couldn't even initialize the stubbed audio hardware!"); } - - char value[PROPERTY_VALUE_MAX]; - property_get("ro.audio.silent", value, "0"); - if (atoi(value)) { - LOGD("Silence is golden"); - mMasterMute = true; - } } AudioFlinger::~AudioFlinger() @@ -172,59 +182,72 @@ AudioFlinger::~AudioFlinger() mAudioRecordThread->exit(); mAudioRecordThread.clear(); } + mHardwareMixerThread.clear(); delete mAudioHardware; // deleting mA2dpAudioInterface also deletes mA2dpOutput; +#ifdef WITH_A2DP + mA2dpMixerThread.clear(); delete mA2dpAudioInterface; - delete [] mMixBuffer; - delete mHardwareAudioMixer; - delete mA2dpAudioMixer; -} - -void AudioFlinger::setOutput(AudioStreamOut* output) -{ - mRequestedOutput = output; +#endif } -void AudioFlinger::doSetOutput(AudioStreamOut* output) + +#ifdef WITH_A2DP +// setA2dpEnabled_l() must be called with AudioFlinger::mLock held +void AudioFlinger::setA2dpEnabled_l(bool enable) { - mSampleRate = output->sampleRate(); - mChannelCount = output->channelCount(); + SortedVector < sp<MixerThread::Track> > tracks; + SortedVector < wp<MixerThread::Track> > activeTracks; + + LOGV_IF(enable, "set output to A2DP\n"); + LOGV_IF(!enable, "set output to hardware audio\n"); - // FIXME - Current mixer implementation only supports stereo output - if (mChannelCount == 1) { - LOGE("Invalid audio hardware channel count"); + // Transfer tracks playing on MUSIC stream from one mixer to the other + if (enable) { + mHardwareMixerThread->getTracks_l(tracks, activeTracks); + mA2dpMixerThread->putTracks_l(tracks, activeTracks); + } else { + mA2dpMixerThread->getTracks_l(tracks, activeTracks); + mHardwareMixerThread->putTracks_l(tracks, activeTracks); } - mFormat = output->format(); - mFrameCount = getOutputFrameCount(output); - mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer); - mOutput = output; + mA2dpEnabled = enable; + mNotifyA2dpChange = true; + mWaitWorkCV.broadcast(); } -size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output) +// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held +void AudioFlinger::checkA2dpEnabledChange_l() { - return output->bufferSize() / output->channelCount() / sizeof(int16_t); + if (mNotifyA2dpChange) { + // Notify AudioSystem of the A2DP activation/deactivation + size_t size = mNotificationClients.size(); + for (size_t i = 0; i < size; i++) { + sp<IBinder> binder = mNotificationClients.itemAt(i).promote(); + if (binder != NULL) { + LOGV("Notifying output change to client %p", binder.get()); + sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder); + client->a2dpEnabledChanged(mA2dpEnabled); + } + } + mNotifyA2dpChange = false; + } } +#endif // WITH_A2DP -#ifdef WITH_A2DP -bool AudioFlinger::streamDisablesA2dp(int streamType) +bool AudioFlinger::streamForcedToSpeaker(int streamType) { - return (streamType == AudioTrack::SYSTEM || - streamType == AudioTrack::RING || - streamType == AudioTrack::ALARM || - streamType == AudioTrack::NOTIFICATION); + // NOTE that streams listed here must not be routed to A2DP by default: + // AudioSystem::routedToA2dpOutput(streamType) == false + return (streamType == AudioSystem::RING || + streamType == AudioSystem::ALARM || + streamType == AudioSystem::NOTIFICATION); } -void AudioFlinger::setA2dpEnabled(bool enable) +bool AudioFlinger::streamDisablesA2dp(int streamType) { - if (enable) { - LOGD("set output to A2DP\n"); - setOutput(mA2dpOutput); - } else { - LOGD("set output to hardware audio\n"); - setOutput(mHardwareOutput); - } + return (streamType == AudioSystem::VOICE_CALL || + streamType == AudioSystem::BLUETOOTH_SCO); } -#endif // WITH_A2DP status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args) { @@ -247,13 +270,672 @@ status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args) return NO_ERROR; } -status_t AudioFlinger::dumpTracks(int fd, const Vector<String16>& args) + +status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + int hardwareStatus = mHardwareStatus; + + if (hardwareStatus == AUDIO_HW_IDLE && mHardwareMixerThread->mStandby) { + hardwareStatus = AUDIO_HW_STANDBY; + } + snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus); + result.append(buffer); + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + snprintf(buffer, SIZE, "Permission Denial: " + "can't dump AudioFlinger from pid=%d, uid=%d\n", + IPCThreadState::self()->getCallingPid(), + IPCThreadState::self()->getCallingUid()); + result.append(buffer); + write(fd, result.string(), result.size()); + return NO_ERROR; +} + +status_t AudioFlinger::dump(int fd, const Vector<String16>& args) +{ + if (checkCallingPermission(String16("android.permission.DUMP")) == false) { + dumpPermissionDenial(fd, args); + } else { + bool locked = false; + for (int i = 0; i < kDumpLockRetries; ++i) { + if (mLock.tryLock() == NO_ERROR) { + locked = true; + break; + } + usleep(kDumpLockSleep); + } + + dumpClients(fd, args); + dumpInternals(fd, args); + mHardwareMixerThread->dump(fd, args); +#ifdef WITH_A2DP + mA2dpMixerThread->dump(fd, args); +#endif + + // dump record client + if (mAudioRecordThread != 0) mAudioRecordThread->dump(fd, args); + + if (mAudioHardware) { + mAudioHardware->dumpState(fd, args); + } + if (locked) mLock.unlock(); + } + return NO_ERROR; +} + +// IAudioFlinger interface + + +sp<IAudioTrack> AudioFlinger::createTrack( + pid_t pid, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + const sp<IMemory>& sharedBuffer, + status_t *status) +{ + sp<MixerThread::Track> track; + sp<TrackHandle> trackHandle; + sp<Client> client; + wp<Client> wclient; + status_t lStatus; + + if (streamType >= AudioSystem::NUM_STREAM_TYPES) { + LOGE("invalid stream type"); + lStatus = BAD_VALUE; + goto Exit; + } + + { + Mutex::Autolock _l(mLock); + + wclient = mClients.valueFor(pid); + + if (wclient != NULL) { + client = wclient.promote(); + } else { + client = new Client(this, pid); + mClients.add(pid, client); + } +#ifdef WITH_A2DP + if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) { + track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format, + channelCount, frameCount, sharedBuffer, &lStatus); + } else +#endif + { + track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format, + channelCount, frameCount, sharedBuffer, &lStatus); + } + } + if (lStatus == NO_ERROR) { + trackHandle = new TrackHandle(track); + } else { + track.clear(); + } + +Exit: + if(status) { + *status = lStatus; + } + return trackHandle; +} + +uint32_t AudioFlinger::sampleRate(int output) const +{ +#ifdef WITH_A2DP + if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { + return mA2dpMixerThread->sampleRate(); + } +#endif + return mHardwareMixerThread->sampleRate(); +} + +int AudioFlinger::channelCount(int output) const +{ +#ifdef WITH_A2DP + if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { + return mA2dpMixerThread->channelCount(); + } +#endif + return mHardwareMixerThread->channelCount(); +} + +int AudioFlinger::format(int output) const +{ +#ifdef WITH_A2DP + if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { + return mA2dpMixerThread->format(); + } +#endif + return mHardwareMixerThread->format(); +} + +size_t AudioFlinger::frameCount(int output) const +{ +#ifdef WITH_A2DP + if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { + return mA2dpMixerThread->frameCount(); + } +#endif + return mHardwareMixerThread->frameCount(); +} + +uint32_t AudioFlinger::latency(int output) const +{ +#ifdef WITH_A2DP + if (output == AudioSystem::AUDIO_OUTPUT_A2DP) { + return mA2dpMixerThread->latency(); + } +#endif + return mHardwareMixerThread->latency(); +} + +status_t AudioFlinger::setMasterVolume(float value) +{ + // check calling permissions + if (!settingsAllowed()) { + return PERMISSION_DENIED; + } + + // when hw supports master volume, don't scale in sw mixer + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; + if (mAudioHardware->setMasterVolume(value) == NO_ERROR) { + value = 1.0f; + } + mHardwareStatus = AUDIO_HW_IDLE; + mHardwareMixerThread->setMasterVolume(value); +#ifdef WITH_A2DP + mA2dpMixerThread->setMasterVolume(value); +#endif + + return NO_ERROR; +} + +status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) +{ + status_t err = NO_ERROR; + + // check calling permissions + if (!settingsAllowed()) { + return PERMISSION_DENIED; + } + if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) { + LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask); + return BAD_VALUE; + } + +#ifdef WITH_A2DP + LOGD("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(), IPCThreadState::self()->getCallingPid()); + if (mode == AudioSystem::MODE_NORMAL && + (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) { + AutoMutex lock(&mLock); + + bool enableA2dp = false; + if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) { + enableA2dp = true; + } + if (mA2dpDisableCount > 0) { + mA2dpSuppressed = enableA2dp; + } else { + setA2dpEnabled_l(enableA2dp); + } + LOGV("setOutput done\n"); + } +#endif + + // do nothing if only A2DP routing is affected + mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP; + if (mask) { + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_HW_GET_ROUTING; + uint32_t r; + err = mAudioHardware->getRouting(mode, &r); + if (err == NO_ERROR) { + r = (r & ~mask) | (routes & mask); + if (mode == AudioSystem::MODE_NORMAL || + (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) { + mSavedRoute = r; + r |= mForcedRoute; + LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute); + } + mHardwareStatus = AUDIO_HW_SET_ROUTING; + err = mAudioHardware->setRouting(mode, r); + } + mHardwareStatus = AUDIO_HW_IDLE; + } + return err; +} + +uint32_t AudioFlinger::getRouting(int mode) const +{ + uint32_t routes = 0; + if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) { + if (mode == AudioSystem::MODE_NORMAL || + (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) { + routes = mSavedRoute; + } else { + mHardwareStatus = AUDIO_HW_GET_ROUTING; + mAudioHardware->getRouting(mode, &routes); + mHardwareStatus = AUDIO_HW_IDLE; + } + } else { + LOGW("Illegal value: getRouting(%d)", mode); + } + return routes; +} + +status_t AudioFlinger::setMode(int mode) +{ + // check calling permissions + if (!settingsAllowed()) { + return PERMISSION_DENIED; + } + if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) { + LOGW("Illegal value: setMode(%d)", mode); + return BAD_VALUE; + } + + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_HW_SET_MODE; + status_t ret = mAudioHardware->setMode(mode); + mHardwareStatus = AUDIO_HW_IDLE; + return ret; +} + +int AudioFlinger::getMode() const +{ + int mode = AudioSystem::MODE_INVALID; + mHardwareStatus = AUDIO_HW_SET_MODE; + mAudioHardware->getMode(&mode); + mHardwareStatus = AUDIO_HW_IDLE; + return mode; +} + +status_t AudioFlinger::setMicMute(bool state) +{ + // check calling permissions + if (!settingsAllowed()) { + return PERMISSION_DENIED; + } + + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_HW_SET_MIC_MUTE; + status_t ret = mAudioHardware->setMicMute(state); + mHardwareStatus = AUDIO_HW_IDLE; + return ret; +} + +bool AudioFlinger::getMicMute() const +{ + bool state = AudioSystem::MODE_INVALID; + mHardwareStatus = AUDIO_HW_GET_MIC_MUTE; + mAudioHardware->getMicMute(&state); + mHardwareStatus = AUDIO_HW_IDLE; + return state; +} + +status_t AudioFlinger::setMasterMute(bool muted) +{ + // check calling permissions + if (!settingsAllowed()) { + return PERMISSION_DENIED; + } + mHardwareMixerThread->setMasterMute(muted); +#ifdef WITH_A2DP + mA2dpMixerThread->setMasterMute(muted); +#endif + return NO_ERROR; +} + +float AudioFlinger::masterVolume() const +{ + return mHardwareMixerThread->masterVolume(); +} + +bool AudioFlinger::masterMute() const +{ + return mHardwareMixerThread->masterMute(); +} + +status_t AudioFlinger::setStreamVolume(int stream, float value) +{ + // check calling permissions + if (!settingsAllowed()) { + return PERMISSION_DENIED; + } + + if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { + return BAD_VALUE; + } + + status_t ret = NO_ERROR; + + if (stream == AudioSystem::VOICE_CALL || + stream == AudioSystem::BLUETOOTH_SCO) { + float hwValue = value; + if (stream == AudioSystem::VOICE_CALL) { + hwValue = (float)AudioSystem::logToLinear(value)/100.0f; + // FIXME: This is a temporary fix to re-base the internally + // generated in-call audio so that it is never muted, which is + // already the case for the hardware routed in-call audio. + // When audio stream handling is reworked, this should be + // addressed more cleanly. Fixes #1324; see discussion at + // http://review.source.android.com/8224 + value = value * 0.99 + 0.01; + } else { // (type == AudioSystem::BLUETOOTH_SCO) + hwValue = 1.0f; + } + + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_SET_VOICE_VOLUME; + ret = mAudioHardware->setVoiceVolume(hwValue); + mHardwareStatus = AUDIO_HW_IDLE; + + } + + mHardwareMixerThread->setStreamVolume(stream, value); +#ifdef WITH_A2DP + mA2dpMixerThread->setStreamVolume(stream, value); +#endif + + return ret; +} + +status_t AudioFlinger::setStreamMute(int stream, bool muted) +{ + // check calling permissions + if (!settingsAllowed()) { + return PERMISSION_DENIED; + } + + if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { + return BAD_VALUE; + } + +#ifdef WITH_A2DP + mA2dpMixerThread->setStreamMute(stream, muted); +#endif + if (stream == AudioSystem::MUSIC) + { + AutoMutex lock(&mHardwareLock); + if (mForcedRoute != 0) + mMusicMuteSaved = muted; + else + mHardwareMixerThread->setStreamMute(stream, muted); + } else { + mHardwareMixerThread->setStreamMute(stream, muted); + } + + + + return NO_ERROR; +} + +float AudioFlinger::streamVolume(int stream) const +{ + if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { + return 0.0f; + } + float value = mHardwareMixerThread->streamVolume(stream); + + if (stream == AudioSystem::VOICE_CALL) { + // FIXME: Re-base internally generated in-call audio, + // reverse of above in setStreamVolume. + value = (value - 0.01) / 0.99; + } + + return value; +} + +bool AudioFlinger::streamMute(int stream) const +{ + if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { + return true; + } + + if (stream == AudioSystem::MUSIC && mForcedRoute != 0) + { + return mMusicMuteSaved; + } + return mHardwareMixerThread->streamMute(stream); +} + +bool AudioFlinger::isMusicActive() const +{ + #ifdef WITH_A2DP + if (isA2dpEnabled()) { + return mA2dpMixerThread->isMusicActive(); + } + #endif + return mHardwareMixerThread->isMusicActive(); +} + +status_t AudioFlinger::setParameter(const char* key, const char* value) +{ + status_t result, result2; + AutoMutex lock(mHardwareLock); + mHardwareStatus = AUDIO_SET_PARAMETER; + + LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid()); + result = mAudioHardware->setParameter(key, value); + if (mA2dpAudioInterface) { + result2 = mA2dpAudioInterface->setParameter(key, value); + if (result2) + result = result2; + } + mHardwareStatus = AUDIO_HW_IDLE; + return result; +} + +size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount) +{ + return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount); +} + +void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client) +{ + + LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid()); + Mutex::Autolock _l(mLock); + + sp<IBinder> binder = client->asBinder(); + if (mNotificationClients.indexOf(binder) < 0) { + LOGV("Adding notification client %p", binder.get()); + binder->linkToDeath(this); + mNotificationClients.add(binder); + client->a2dpEnabledChanged(isA2dpEnabled()); + } +} + +void AudioFlinger::binderDied(const wp<IBinder>& who) { + + LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid()); + Mutex::Autolock _l(mLock); + + IBinder *binder = who.unsafe_get(); + + if (binder != NULL) { + int index = mNotificationClients.indexOf(binder); + if (index >= 0) { + LOGV("Removing notification client %p", binder); + mNotificationClients.removeAt(index); + } + } +} + +void AudioFlinger::removeClient(pid_t pid) +{ + LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid()); + Mutex::Autolock _l(mLock); + mClients.removeItem(pid); +} + +bool AudioFlinger::isA2dpEnabled() const +{ + return mA2dpEnabled; +} + +void AudioFlinger::handleForcedSpeakerRoute(int command) +{ + switch(command) { + case ACTIVE_TRACK_ADDED: + { + AutoMutex lock(mHardwareLock); + if (mForcedSpeakerCount++ == 0) { + mRouteRestoreTime = 0; + mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC); + if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) { + LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER); + mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true); + mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; + mAudioHardware->setMasterVolume(0); + usleep(mHardwareMixerThread->latency()*1000); + mHardwareStatus = AUDIO_HW_SET_ROUTING; + mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER); + mHardwareStatus = AUDIO_HW_IDLE; + // delay track start so that audio hardware has time to siwtch routes + usleep(kStartSleepTime); + mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; + mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume()); + mHardwareStatus = AUDIO_HW_IDLE; + } + mForcedRoute = AudioSystem::ROUTE_SPEAKER; + } + LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount); + } + break; + case ACTIVE_TRACK_REMOVED: + { + AutoMutex lock(mHardwareLock); + if (mForcedSpeakerCount > 0){ + if (--mForcedSpeakerCount == 0) { + mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000); + } + LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount); + } else { + LOGE("mForcedSpeakerCount is already zero"); + } + } + break; + case CHECK_ROUTE_RESTORE_TIME: + case FORCE_ROUTE_RESTORE: + if (mRouteRestoreTime) { + AutoMutex lock(mHardwareLock); + if (mRouteRestoreTime && + (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) { + mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved); + mForcedRoute = 0; + if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) { + mHardwareStatus = AUDIO_HW_SET_ROUTING; + mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute); + mHardwareStatus = AUDIO_HW_IDLE; + LOGV("Route forced to Speaker OFF %08x", mSavedRoute); + } + mRouteRestoreTime = 0; + } + } + break; + } +} + +#ifdef WITH_A2DP +// handleStreamDisablesA2dp_l() must be called with AudioFlinger::mLock held +void AudioFlinger::handleStreamDisablesA2dp_l(int command) +{ + switch(command) { + case ACTIVE_TRACK_ADDED: + { + if (mA2dpDisableCount++ == 0) { + if (mA2dpEnabled) { + setA2dpEnabled_l(false); + mA2dpSuppressed = true; + } + } + LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount); + } + break; + case ACTIVE_TRACK_REMOVED: + { + if (mA2dpDisableCount > 0) { + if (--mA2dpDisableCount == 0) { + if (mA2dpSuppressed) { + setA2dpEnabled_l(true); + mA2dpSuppressed = false; + } + } + LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount); + } else { + LOGE("mA2dpDisableCount is already zero"); + } + } + break; + } +} +#endif + +// ---------------------------------------------------------------------------- + +AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType) + : Thread(false), + mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType), + mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0), + mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false), + mInWrite(false) +{ + mSampleRate = output->sampleRate(); + mChannelCount = output->channelCount(); + + // FIXME - Current mixer implementation only supports stereo output + if (mChannelCount == 1) { + LOGE("Invalid audio hardware channel count"); + } + + mFormat = output->format(); + mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t); + mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate()); + + // FIXME - Current mixer implementation only supports stereo output: Always + // Allocate a stereo buffer even if HW output is mono. + mMixBuffer = new int16_t[mFrameCount * 2]; + memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t)); +} + +AudioFlinger::MixerThread::~MixerThread() +{ + delete [] mMixBuffer; + delete mAudioMixer; +} + +status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args) +{ + dumpInternals(fd, args); + dumpTracks(fd, args); + return NO_ERROR; +} + +status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args) { const size_t SIZE = 256; char buffer[SIZE]; String8 result; - result.append("Tracks:\n"); + snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType); + result.append(buffer); result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n"); for (size_t i = 0; i < mTracks.size(); ++i) { wp<Track> wTrack = mTracks[i]; @@ -266,7 +948,8 @@ status_t AudioFlinger::dumpTracks(int fd, const Vector<String16>& args) } } - result.append("Active Tracks:\n"); + snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType); + result.append(buffer); result.append(" Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n"); for (size_t i = 0; i < mActiveTracks.size(); ++i) { wp<Track> wTrack = mTracks[i]; @@ -282,13 +965,15 @@ status_t AudioFlinger::dumpTracks(int fd, const Vector<String16>& args) return NO_ERROR; } -status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args) +status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args) { const size_t SIZE = 256; char buffer[SIZE]; String8 result; - snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", audioMixer()->trackNames()); + snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType); + result.append(buffer); + snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames()); result.append(buffer); snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime)); result.append(buffer); @@ -300,85 +985,86 @@ status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args) result.append(buffer); snprintf(buffer, SIZE, "standby: %d\n", mStandby); result.append(buffer); - snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus); - result.append(buffer); write(fd, result.string(), result.size()); return NO_ERROR; } -status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args) -{ - const size_t SIZE = 256; - char buffer[SIZE]; - String8 result; - snprintf(buffer, SIZE, "Permission Denial: " - "can't dump AudioFlinger from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - result.append(buffer); - write(fd, result.string(), result.size()); - return NO_ERROR; -} - -status_t AudioFlinger::dump(int fd, const Vector<String16>& args) -{ - if (checkCallingPermission(String16("android.permission.DUMP")) == false) { - dumpPermissionDenial(fd, args); - } else { - AutoMutex lock(&mLock); - - dumpClients(fd, args); - dumpTracks(fd, args); - dumpInternals(fd, args); - if (mAudioHardware) { - mAudioHardware->dumpState(fd, args); - } - } - return NO_ERROR; -} - // Thread virtuals -bool AudioFlinger::threadLoop() +bool AudioFlinger::MixerThread::threadLoop() { unsigned long sleepTime = kBufferRecoveryInUsecs; int16_t* curBuf = mMixBuffer; Vector< sp<Track> > tracksToRemove; size_t enabledTracks = 0; - nsecs_t standbyTime = systemTime(); + nsecs_t standbyTime = systemTime(); + size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t); + nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2; + +#ifdef WITH_A2DP + bool outputTrackActive = false; +#endif do { enabledTracks = 0; - { // scope for the mLock + { // scope for the AudioFlinger::mLock - Mutex::Autolock _l(mLock); + Mutex::Autolock _l(mAudioFlinger->mLock); + +#ifdef WITH_A2DP + if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) { + if (outputTrackActive) { + mAudioFlinger->mLock.unlock(); + mOutputTrack->stop(); + mAudioFlinger->mLock.lock(); + outputTrackActive = false; + } + } + mAudioFlinger->checkA2dpEnabledChange_l(); +#endif + const SortedVector< wp<Track> >& activeTracks = mActiveTracks; // put audio hardware into standby after short delay if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) { // wait until we have something to do... - LOGV("Audio hardware entering standby\n"); - mHardwareStatus = AUDIO_HW_STANDBY; + LOGV("Audio hardware entering standby, output %d\n", mOutputType); if (!mStandby) { mOutput->standby(); mStandby = true; } - mHardwareStatus = AUDIO_HW_IDLE; + +#ifdef WITH_A2DP + if (outputTrackActive) { + mAudioFlinger->mLock.unlock(); + mOutputTrack->stop(); + mAudioFlinger->mLock.lock(); + outputTrackActive = false; + } +#endif + if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { + mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE); + } // we're about to wait, flush the binder command buffer IPCThreadState::self()->flushCommands(); - mWaitWorkCV.wait(mLock); - LOGV("Audio hardware exiting standby\n"); + mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock); + LOGV("Audio hardware exiting standby, output %d\n", mOutputType); + + if (mMasterMute == false) { + char value[PROPERTY_VALUE_MAX]; + property_get("ro.audio.silent", value, "0"); + if (atoi(value)) { + LOGD("Silence is golden"); + setMasterMute(true); + } + } + standbyTime = systemTime() + kStandbyTimeInNsecs; continue; } - // check for change in output - if (mRequestedOutput != mOutput) { - - // put current output into standby mode - if (mOutput) mOutput->standby(); - - // change output - doSetOutput(mRequestedOutput); + // Forced route to speaker is handled by hardware mixer thread + if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { + mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME); } // find out which tracks need to be processed @@ -396,7 +1082,7 @@ bool AudioFlinger::threadLoop() if (cblk->framesReady() && (track->isReady() || track->isStopped()) && !track->isPaused()) { - //LOGD("u=%08x, s=%08x [OK]", u, s); + //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server); // compute volume for this track int16_t left, right; @@ -451,7 +1137,7 @@ bool AudioFlinger::threadLoop() track->mRetryCount = kMaxTrackRetries; enabledTracks++; } else { - //LOGD("u=%08x, s=%08x [NOT READY]", u, s); + //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server); if (track->isStopped()) { track->reset(); } @@ -478,22 +1164,33 @@ bool AudioFlinger::threadLoop() if (UNLIKELY(count)) { for (size_t i=0 ; i<count ; i++) { const sp<Track>& track = tracksToRemove[i]; - removeActiveTrack(track); + removeActiveTrack_l(track); if (track->isTerminated()) { mTracks.remove(track); - mAudioMixer->deleteTrackName(track->mName); + deleteTrackName_l(track->mName); } } - } + } } + if (LIKELY(enabledTracks)) { // mix buffers... mAudioMixer->process(curBuf); +#ifdef WITH_A2DP + if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) { + if (!outputTrackActive) { + LOGV("starting output track in mixer for output %d", mOutputType); + mOutputTrack->start(); + outputTrackActive = true; + } + mOutputTrack->write(curBuf, mFrameCount); + } +#endif + // output audio to hardware mLastWriteTime = systemTime(); mInWrite = true; - size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t); mOutput->write(curBuf, mixBufferSize); mNumWrites++; mInWrite = false; @@ -501,18 +1198,30 @@ bool AudioFlinger::threadLoop() nsecs_t temp = systemTime(); standbyTime = temp + kStandbyTimeInNsecs; nsecs_t delta = temp - mLastWriteTime; - nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2; if (delta > maxPeriod) { LOGW("write blocked for %llu msecs", ns2ms(delta)); mNumDelayedWrites++; } sleepTime = kBufferRecoveryInUsecs; - } else { + } else { +#ifdef WITH_A2DP + if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) { + if (outputTrackActive) { + mOutputTrack->write(curBuf, 0); + if (mOutputTrack->bufferQueueEmpty()) { + mOutputTrack->stop(); + outputTrackActive = false; + } else { + standbyTime = systemTime() + kStandbyTimeInNsecs; + } + } + } +#endif // There was nothing to mix this round, which means all // active tracks were late. Sleep a little bit to give // them another chance. If we're too late, the audio // hardware will zero-fill for us. - LOGV("no buffers - usleep(%lu)", sleepTime); + //LOGV("no buffers - usleep(%lu)", sleepTime); usleep(sleepTime); if (sleepTime < kMaxBufferRecoveryInUsecs) { sleepTime += kBufferRecoveryInUsecs; @@ -528,106 +1237,151 @@ bool AudioFlinger::threadLoop() return false; } -status_t AudioFlinger::readyToRun() +status_t AudioFlinger::MixerThread::readyToRun() { if (mSampleRate == 0) { LOGE("No working audio driver found."); return NO_INIT; } - LOGI("AudioFlinger's main thread ready to run."); + LOGI("AudioFlinger's thread ready to run for output %d", mOutputType); return NO_ERROR; } -void AudioFlinger::onFirstRef() +void AudioFlinger::MixerThread::onFirstRef() { - run("AudioFlinger", ANDROID_PRIORITY_URGENT_AUDIO); + const size_t SIZE = 256; + char buffer[SIZE]; + + snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType); + + run(buffer, ANDROID_PRIORITY_URGENT_AUDIO); } -// IAudioFlinger interface -sp<IAudioTrack> AudioFlinger::createTrack( - pid_t pid, +// MixerThread::createTrack_l() must be called with AudioFlinger::mLock held +sp<AudioFlinger::MixerThread::Track> AudioFlinger::MixerThread::createTrack_l( + const sp<AudioFlinger::Client>& client, int streamType, uint32_t sampleRate, int format, int channelCount, int frameCount, - uint32_t flags, const sp<IMemory>& sharedBuffer, status_t *status) { sp<Track> track; - sp<TrackHandle> trackHandle; - sp<Client> client; - wp<Client> wclient; status_t lStatus; - - if (streamType >= AudioTrack::NUM_STREAM_TYPES) { - LOGE("invalid stream type"); + + // Resampler implementation limits input sampling rate to 2 x output sampling rate. + if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) { + LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate); lStatus = BAD_VALUE; goto Exit; } - // Resampler implementation limits input sampling rate to 2 x output sampling rate. - if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) { - LOGE("Sample rate out of range: %d", sampleRate); - lStatus = BAD_VALUE; + + if (mSampleRate == 0) { + LOGE("Audio driver not initialized."); + lStatus = NO_INIT; goto Exit; } - { - Mutex::Autolock _l(mLock); + track = new Track(this, client, streamType, sampleRate, format, + channelCount, frameCount, sharedBuffer); + if (track->getCblk() == NULL) { + lStatus = NO_MEMORY; + goto Exit; + } + mTracks.add(track); + lStatus = NO_ERROR; - if (mSampleRate == 0) { - LOGE("Audio driver not initialized."); - lStatus = NO_INIT; - goto Exit; +Exit: + if(status) { + *status = lStatus; + } + return track; +} + +// getTracks_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::getTracks_l( + SortedVector < sp<Track> >& tracks, + SortedVector < wp<Track> >& activeTracks) +{ + size_t size = mTracks.size(); + LOGV ("MixerThread::getTracks_l() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType, mTracks.size(), mActiveTracks.size()); + for (size_t i = 0; i < size; i++) { + sp<Track> t = mTracks[i]; + if (AudioSystem::routedToA2dpOutput(t->mStreamType)) { + tracks.add(t); + int j = mActiveTracks.indexOf(t); + if (j >= 0) { + t = mActiveTracks[j].promote(); + if (t != NULL) { + activeTracks.add(t); + } + } } + } - wclient = mClients.valueFor(pid); + size = activeTracks.size(); + for (size_t i = 0; i < size; i++) { + removeActiveTrack_l(activeTracks[i]); + } + + size = tracks.size(); + for (size_t i = 0; i < size; i++) { + sp<Track> t = tracks[i]; + mTracks.remove(t); + deleteTrackName_l(t->name()); + } +} - if (wclient != NULL) { - client = wclient.promote(); - } else { - client = new Client(this, pid); - mClients.add(pid, client); - } +// putTracks_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::putTracks_l( + SortedVector < sp<Track> >& tracks, + SortedVector < wp<Track> >& activeTracks) +{ - track = new Track(this, client, streamType, sampleRate, format, - channelCount, frameCount, sharedBuffer); - mTracks.add(track); - trackHandle = new TrackHandle(track); + LOGV ("MixerThread::putTracks_l() for output %d, tracks.size %d, activeTracks.size %d", mOutputType, tracks.size(), activeTracks.size()); - lStatus = NO_ERROR; - } + size_t size = tracks.size(); + for (size_t i = 0; i < size ; i++) { + sp<Track> t = tracks[i]; + int name = getTrackName_l(); -Exit: - if(status) { - *status = lStatus; + if (name < 0) return; + + t->mName = name; + t->mMixerThread = this; + mTracks.add(t); + + int j = activeTracks.indexOf(t); + if (j >= 0) { + addActiveTrack_l(t); + } } - return trackHandle; } -uint32_t AudioFlinger::sampleRate() const +uint32_t AudioFlinger::MixerThread::sampleRate() const { return mSampleRate; } -int AudioFlinger::channelCount() const +int AudioFlinger::MixerThread::channelCount() const { return mChannelCount; } -int AudioFlinger::format() const +int AudioFlinger::MixerThread::format() const { return mFormat; } -size_t AudioFlinger::frameCount() const +size_t AudioFlinger::MixerThread::frameCount() const { return mFrameCount; } -uint32_t AudioFlinger::latency() const +uint32_t AudioFlinger::MixerThread::latency() const { if (mOutput) { return mOutput->latency(); @@ -637,260 +1391,67 @@ uint32_t AudioFlinger::latency() const } } -status_t AudioFlinger::setMasterVolume(float value) +status_t AudioFlinger::MixerThread::setMasterVolume(float value) { - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - // when hw supports master volume, don't scale in sw mixer - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; - if (mAudioHardware->setMasterVolume(value) == NO_ERROR) { - mMasterVolume = 1.0f; - } - else { - mMasterVolume = value; - } - mHardwareStatus = AUDIO_HW_IDLE; + mMasterVolume = value; return NO_ERROR; } -status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) -{ - status_t err = NO_ERROR; - - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - if ((mode < AudioSystem::MODE_CURRENT) || (mode >= AudioSystem::NUM_MODES)) { - LOGW("Illegal value: setRouting(%d, %u, %u)", mode, routes, mask); - return BAD_VALUE; - } - -#ifdef WITH_A2DP - LOGD("setRouting %d %d %d\n", mode, routes, mask); - if (mode == AudioSystem::MODE_NORMAL && - (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) { - AutoMutex lock(&mLock); - - bool enableA2dp = false; - if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) { - if (mA2dpDisableCount > 0) - mA2dpSuppressed = true; - else - enableA2dp = true; - } - setA2dpEnabled(enableA2dp); - LOGD("setOutput done\n"); - } -#endif - - // do nothing if only A2DP routing is affected - mask &= ~AudioSystem::ROUTE_BLUETOOTH_A2DP; - if (mask) { - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_GET_ROUTING; - uint32_t r; - err = mAudioHardware->getRouting(mode, &r); - if (err == NO_ERROR) { - r = (r & ~mask) | (routes & mask); - mHardwareStatus = AUDIO_HW_SET_ROUTING; - err = mAudioHardware->setRouting(mode, r); - } - mHardwareStatus = AUDIO_HW_IDLE; - } - return err; -} - -uint32_t AudioFlinger::getRouting(int mode) const -{ - uint32_t routes = 0; - if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) { - mHardwareStatus = AUDIO_HW_GET_ROUTING; - mAudioHardware->getRouting(mode, &routes); - mHardwareStatus = AUDIO_HW_IDLE; - } else { - LOGW("Illegal value: getRouting(%d)", mode); - } - return routes; -} - -status_t AudioFlinger::setMode(int mode) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) { - LOGW("Illegal value: setMode(%d)", mode); - return BAD_VALUE; - } - - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MODE; - status_t ret = mAudioHardware->setMode(mode); - mHardwareStatus = AUDIO_HW_IDLE; - return ret; -} - -int AudioFlinger::getMode() const -{ - int mode = AudioSystem::MODE_INVALID; - mHardwareStatus = AUDIO_HW_SET_MODE; - mAudioHardware->getMode(&mode); - mHardwareStatus = AUDIO_HW_IDLE; - return mode; -} - -status_t AudioFlinger::setMicMute(bool state) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_HW_SET_MIC_MUTE; - status_t ret = mAudioHardware->setMicMute(state); - mHardwareStatus = AUDIO_HW_IDLE; - return ret; -} - -bool AudioFlinger::getMicMute() const +status_t AudioFlinger::MixerThread::setMasterMute(bool muted) { - bool state = AudioSystem::MODE_INVALID; - mHardwareStatus = AUDIO_HW_GET_MIC_MUTE; - mAudioHardware->getMicMute(&state); - mHardwareStatus = AUDIO_HW_IDLE; - return state; -} - -status_t AudioFlinger::setMasterMute(bool muted) -{ - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - mMasterMute = muted; return NO_ERROR; } -float AudioFlinger::masterVolume() const +float AudioFlinger::MixerThread::masterVolume() const { return mMasterVolume; } -bool AudioFlinger::masterMute() const +bool AudioFlinger::MixerThread::masterMute() const { return mMasterMute; } -status_t AudioFlinger::setStreamVolume(int stream, float value) +status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value) { - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) { - return BAD_VALUE; - } - - status_t ret = NO_ERROR; - if (stream == AudioTrack::VOICE_CALL) { - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_SET_VOICE_VOLUME; - ret = mAudioHardware->setVoiceVolume(value); - mHardwareStatus = AUDIO_HW_IDLE; - // FIXME: This is a temporary fix to re-base the internally - // generated in-call audio so that it is never muted, which is - // already the case for the hardware routed in-call audio. - // When audio stream handling is reworked, this should be - // addressed more cleanly. Fixes #1324; see discussion at - // http://review.source.android.com/8224 - mStreamTypes[stream].volume = value * (1.0 - 1.0 / 6.0) + (1.0 / 6.0); - } else { - mStreamTypes[stream].volume = value; - } - return ret; + mStreamTypes[stream].volume = value; + return NO_ERROR; } -status_t AudioFlinger::setStreamMute(int stream, bool muted) +status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted) { - // check calling permissions - if (!settingsAllowed()) { - return PERMISSION_DENIED; - } - - if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) { - return BAD_VALUE; - } mStreamTypes[stream].mute = muted; return NO_ERROR; } -float AudioFlinger::streamVolume(int stream) const +float AudioFlinger::MixerThread::streamVolume(int stream) const { - if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) { - return 0.0f; - } - if (stream == AudioTrack::VOICE_CALL) { - // FIXME: Re-base internally generated in-call audio, - // reverse of above in setStreamVolume. - return (mStreamTypes[stream].volume - (1.0 / 6.0)) / (1.0 - 1.0 / 6.0); - } return mStreamTypes[stream].volume; } -bool AudioFlinger::streamMute(int stream) const +bool AudioFlinger::MixerThread::streamMute(int stream) const { - if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) { - return true; - } return mStreamTypes[stream].mute; } -bool AudioFlinger::isMusicActive() const +bool AudioFlinger::MixerThread::isMusicActive() const { size_t count = mActiveTracks.size(); for (size_t i = 0 ; i < count ; ++i) { sp<Track> t = mActiveTracks[i].promote(); if (t == 0) continue; Track* const track = t.get(); - if (t->mStreamType == AudioTrack::MUSIC) + if (t->mStreamType == AudioSystem::MUSIC) return true; } return false; } -status_t AudioFlinger::setParameter(const char* key, const char* value) -{ - status_t result, result2; - AutoMutex lock(mHardwareLock); - mHardwareStatus = AUDIO_SET_PARAMETER; - result = mAudioHardware->setParameter(key, value); - if (mA2dpAudioInterface) { - result2 = mA2dpAudioInterface->setParameter(key, value); - if (result2) - result = result2; - } - mHardwareStatus = AUDIO_HW_IDLE; - return result; -} - -void AudioFlinger::removeClient(pid_t pid) -{ - Mutex::Autolock _l(mLock); - mClients.removeItem(pid); -} - -status_t AudioFlinger::addTrack(const sp<Track>& track) +// addTrack_l() must be called with AudioFlinger::mLock held +status_t AudioFlinger::MixerThread::addTrack_l(const sp<Track>& track) { - Mutex::Autolock _l(mLock); + status_t status = ALREADY_EXISTS; // here the track could be either new, or restarted // in both cases "unstop" the track @@ -903,139 +1464,135 @@ status_t AudioFlinger::addTrack(const sp<Track>& track) } // set retry count for buffer fill track->mRetryCount = kMaxTrackStartupRetries; - LOGV("mWaitWorkCV.broadcast"); - mWaitWorkCV.broadcast(); - if (mActiveTracks.indexOf(track) < 0) { // the track is newly added, make sure it fills up all its // buffers before playing. This is to ensure the client will // effectively get the latency it requested. track->mFillingUpStatus = Track::FS_FILLING; track->mResetDone = false; - addActiveTrack(track); - return NO_ERROR; + addActiveTrack_l(track); + status = NO_ERROR; } - return ALREADY_EXISTS; -} + + LOGV("mWaitWorkCV.broadcast"); + mAudioFlinger->mWaitWorkCV.broadcast(); -void AudioFlinger::removeTrack(wp<Track> track, int name) -{ - Mutex::Autolock _l(mLock); - sp<Track> t = track.promote(); - if (t!=NULL && (t->mState <= TrackBase::STOPPED)) { - remove_track_l(track, name); - } + return status; } -void AudioFlinger::remove_track_l(wp<Track> track, int name) +// removeTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::removeTrack_l(wp<Track> track, int name) { sp<Track> t = track.promote(); - if (t!=NULL) { + if (t!=NULL && (t->mState <= TrackBase::STOPPED)) { t->reset(); + deleteTrackName_l(name); + removeActiveTrack_l(track); + mAudioFlinger->mWaitWorkCV.broadcast(); } - audioMixer()->deleteTrackName(name); - removeActiveTrack(track); - mWaitWorkCV.broadcast(); } -void AudioFlinger::destroyTrack(const sp<Track>& track) +// destroyTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::destroyTrack_l(const sp<Track>& track) { - // NOTE: We're acquiring a strong reference on the track before - // acquiring the lock, this is to make sure removing it from - // mTracks won't cause the destructor to be called while the lock is - // held (note that technically, 'track' could be a reference to an item - // in mTracks, which is why we need to do this). - sp<Track> keep(track); - Mutex::Autolock _l(mLock); track->mState = TrackBase::TERMINATED; if (mActiveTracks.indexOf(track) < 0) { LOGV("remove track (%d) and delete from mixer", track->name()); mTracks.remove(track); - audioMixer()->deleteTrackName(keep->name()); + deleteTrackName_l(track->name()); } } -void AudioFlinger::addActiveTrack(const wp<Track>& t) +// addActiveTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t) { mActiveTracks.add(t); + // Force routing to speaker for certain stream types + // The forced routing to speaker is managed by hardware mixer + if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { + sp<Track> track = t.promote(); + if (track == NULL) return; + + if (streamForcedToSpeaker(track->type())) { + mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED); + } #ifdef WITH_A2DP - // disable A2DP for certain stream types - sp<Track> track = t.promote(); - if (streamDisablesA2dp(track->type())) { - if (mA2dpDisableCount++ == 0 && isA2dpEnabled()) { - setA2dpEnabled(false); - mA2dpSuppressed = true; - LOGD("mA2dpSuppressed = true\n"); + // AudioFlinger::mLock must be locked before calling + // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). + if (streamDisablesA2dp(track->type())) { + mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED); } - LOGD("mA2dpDisableCount incremented to %d\n", mA2dpDisableCount); - } #endif + } } -void AudioFlinger::removeActiveTrack(const wp<Track>& t) +// removeActiveTrack_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t) { mActiveTracks.remove(t); + + // Force routing to speaker for certain stream types + // The forced routing to speaker is managed by hardware mixer + if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) { + sp<Track> track = t.promote(); + if (track == NULL) return; + + if (streamForcedToSpeaker(track->type())) { + mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED); + } #ifdef WITH_A2DP - // disable A2DP for certain stream types - sp<Track> track = t.promote(); - if (streamDisablesA2dp(track->type())) { - if (mA2dpDisableCount > 0) { - mA2dpDisableCount--; - if (mA2dpDisableCount == 0 && mA2dpSuppressed) { - setA2dpEnabled(true); - mA2dpSuppressed = false; - } - LOGD("mA2dpDisableCount decremented to %d\n", mA2dpDisableCount); - } else - LOGE("mA2dpDisableCount is already zero"); - } + // AudioFlinger::mLock must be locked before calling + // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). + if (streamDisablesA2dp(track->type())) { + mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED); + } #endif + } } -// ---------------------------------------------------------------------------- - -AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid) - : RefBase(), - mAudioFlinger(audioFlinger), - mMemoryDealer(new MemoryDealer(1024*1024)), - mPid(pid) +// getTrackName_l() must be called with AudioFlinger::mLock held +int AudioFlinger::MixerThread::getTrackName_l() { - // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer + return mAudioMixer->getTrackName(); } -AudioFlinger::Client::~Client() +// deleteTrackName_l() must be called with AudioFlinger::mLock held +void AudioFlinger::MixerThread::deleteTrackName_l(int name) { - mAudioFlinger->removeClient(mPid); + mAudioMixer->deleteTrackName(name); } -const sp<MemoryDealer>& AudioFlinger::Client::heap() const +size_t AudioFlinger::MixerThread::getOutputFrameCount() { - return mMemoryDealer; + return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t); } // ---------------------------------------------------------------------------- -AudioFlinger::TrackBase::TrackBase( - const sp<AudioFlinger>& audioFlinger, +// TrackBase constructor must be called with AudioFlinger::mLock held +AudioFlinger::MixerThread::TrackBase::TrackBase( + const sp<MixerThread>& mixerThread, const sp<Client>& client, int streamType, uint32_t sampleRate, int format, int channelCount, int frameCount, + uint32_t flags, const sp<IMemory>& sharedBuffer) : RefBase(), - mAudioFlinger(audioFlinger), + mMixerThread(mixerThread), mClient(client), mStreamType(streamType), mFrameCount(0), mState(IDLE), mClientTid(-1), mFormat(format), - mFlags(0) + mFlags(flags & ~SYSTEM_FLAGS_MASK) { - mName = audioFlinger->audioMixer()->getTrackName(); + mName = mixerThread->getTrackName_l(); + LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid()); if (mName < 0) { LOGE("no more track names availlable"); return; @@ -1043,7 +1600,6 @@ AudioFlinger::TrackBase::TrackBase( LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); - // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize); size_t size = sizeof(audio_track_cblk_t); size_t bufferSize = frameCount*channelCount*sizeof(int16_t); @@ -1051,41 +1607,60 @@ AudioFlinger::TrackBase::TrackBase( size += bufferSize; } - mCblkMemory = client->heap()->allocate(size); - if (mCblkMemory != 0) { - mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer()); - if (mCblk) { // construct the shared structure in-place. - new(mCblk) audio_track_cblk_t(); - // clear all buffers - mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; - if (sharedBuffer == 0) { - mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); - memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); - // Force underrun condition to avoid false underrun callback until first data is - // written to buffer - mCblk->flowControlFlag = 1; - } else { - mBuffer = sharedBuffer->pointer(); + if (client != NULL) { + mCblkMemory = client->heap()->allocate(size); + if (mCblkMemory != 0) { + mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer()); + if (mCblk) { // construct the shared structure in-place. + new(mCblk) audio_track_cblk_t(); + // clear all buffers + mCblk->frameCount = frameCount; + mCblk->sampleRate = sampleRate; + mCblk->channels = channelCount; + if (sharedBuffer == 0) { + mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); + memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); + // Force underrun condition to avoid false underrun callback until first data is + // written to buffer + mCblk->flowControlFlag = 1; + } else { + mBuffer = sharedBuffer->pointer(); + } + mBufferEnd = (uint8_t *)mBuffer + bufferSize; } - mBufferEnd = (uint8_t *)mBuffer + bufferSize; + } else { + LOGE("not enough memory for AudioTrack size=%u", size); + client->heap()->dump("AudioTrack"); + return; } - } else { - LOGE("not enough memory for AudioTrack size=%u", size); - client->heap()->dump("AudioTrack"); - return; - } + } else { + mCblk = (audio_track_cblk_t *)(new uint8_t[size]); + if (mCblk) { // construct the shared structure in-place. + new(mCblk) audio_track_cblk_t(); + // clear all buffers + mCblk->frameCount = frameCount; + mCblk->sampleRate = sampleRate; + mCblk->channels = channelCount; + mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); + memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); + // Force underrun condition to avoid false underrun callback until first data is + // written to buffer + mCblk->flowControlFlag = 1; + mBufferEnd = (uint8_t *)mBuffer + bufferSize; + } + } } -AudioFlinger::TrackBase::~TrackBase() +AudioFlinger::MixerThread::TrackBase::~TrackBase() { - mCblk->~audio_track_cblk_t(); // destroy our shared-structure. + if (mCblk) { + mCblk->~audio_track_cblk_t(); // destroy our shared-structure. + } mCblkMemory.clear(); // and free the shared memory mClient.clear(); } -void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer) +void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer) { buffer->raw = 0; mFrameCount = buffer->frameCount; @@ -1093,7 +1668,7 @@ void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer) buffer->frameCount = 0; } -bool AudioFlinger::TrackBase::step() { +bool AudioFlinger::MixerThread::TrackBase::step() { bool result; audio_track_cblk_t* cblk = this->cblk(); @@ -1105,31 +1680,31 @@ bool AudioFlinger::TrackBase::step() { return result; } -void AudioFlinger::TrackBase::reset() { +void AudioFlinger::MixerThread::TrackBase::reset() { audio_track_cblk_t* cblk = this->cblk(); cblk->user = 0; cblk->server = 0; cblk->userBase = 0; cblk->serverBase = 0; - mFlags = 0; + mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK); LOGV("TrackBase::reset"); } -sp<IMemory> AudioFlinger::TrackBase::getCblk() const +sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const { return mCblkMemory; } -int AudioFlinger::TrackBase::sampleRate() const { +int AudioFlinger::MixerThread::TrackBase::sampleRate() const { return mCblk->sampleRate; } -int AudioFlinger::TrackBase::channelCount() const { +int AudioFlinger::MixerThread::TrackBase::channelCount() const { return mCblk->channels; } -void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const { +void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const { audio_track_cblk_t* cblk = this->cblk(); int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels; int16_t *bufferEnd = bufferStart + frames * cblk->channels; @@ -1148,8 +1723,9 @@ void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const // ---------------------------------------------------------------------------- -AudioFlinger::Track::Track( - const sp<AudioFlinger>& audioFlinger, +// Track constructor must be called with AudioFlinger::mLock held +AudioFlinger::MixerThread::Track::Track( + const sp<MixerThread>& mixerThread, const sp<Client>& client, int streamType, uint32_t sampleRate, @@ -1157,7 +1733,7 @@ AudioFlinger::Track::Track( int channelCount, int frameCount, const sp<IMemory>& sharedBuffer) - : TrackBase(audioFlinger, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer) + : TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, 0, sharedBuffer) { mVolume[0] = 1.0f; mVolume[1] = 1.0f; @@ -1165,23 +1741,36 @@ AudioFlinger::Track::Track( mSharedBuffer = sharedBuffer; } -AudioFlinger::Track::~Track() +AudioFlinger::MixerThread::Track::~Track() { wp<Track> weak(this); // never create a strong ref from the dtor + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); mState = TERMINATED; - mAudioFlinger->removeTrack(weak, mName); + mMixerThread->removeTrack_l(weak, mName); } -void AudioFlinger::Track::destroy() +void AudioFlinger::MixerThread::Track::destroy() { - mAudioFlinger->destroyTrack(this); + // NOTE: destroyTrack_l() can remove a strong reference to this Track + // by removing it from mTracks vector, so there is a risk that this Tracks's + // desctructor is called. As the destructor needs to lock AudioFlinger::mLock, + // we must acquire a strong reference on this Track before locking AudioFlinger::mLock + // here so that the destructor is called only when exiting this function. + // On the other hand, as long as Track::destroy() is only called by + // TrackHandle destructor, the TrackHandle still holds a strong ref on + // this Track with its member mTrack. + sp<Track> keep(this); + { // scope for AudioFlinger::mLock + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); + mMixerThread->destroyTrack_l(this); + } } -void AudioFlinger::Track::dump(char* buffer, size_t size) +void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size) { snprintf(buffer, size, " %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n", mName - AudioMixer::TRACK0, - mClient->pid(), + (mClient == NULL) ? getpid() : mClient->pid(), mStreamType, mFormat, mCblk->channels, @@ -1196,7 +1785,7 @@ void AudioFlinger::Track::dump(char* buffer, size_t size) mCblk->user); } -status_t AudioFlinger::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer) +status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer) { audio_track_cblk_t* cblk = this->cblk(); uint32_t framesReady; @@ -1236,53 +1825,55 @@ getNextBuffer_exit: return NOT_ENOUGH_DATA; } -bool AudioFlinger::Track::isReady() const { +bool AudioFlinger::MixerThread::Track::isReady() const { if (mFillingUpStatus != FS_FILLING) return true; if (mCblk->framesReady() >= mCblk->frameCount || mCblk->forceReady) { mFillingUpStatus = FS_FILLED; mCblk->forceReady = 0; + LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType); return true; } return false; } -status_t AudioFlinger::Track::start() +status_t AudioFlinger::MixerThread::Track::start() { - LOGV("start(%d)", mName); - mAudioFlinger->addTrack(this); + LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); + mMixerThread->addTrack_l(this); return NO_ERROR; } -void AudioFlinger::Track::stop() +void AudioFlinger::MixerThread::Track::stop() { - LOGV("stop(%d)", mName); - Mutex::Autolock _l(mAudioFlinger->mLock); + LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); if (mState > STOPPED) { mState = STOPPED; // If the track is not active (PAUSED and buffers full), flush buffers - if (mAudioFlinger->mActiveTracks.indexOf(this) < 0) { + if (mMixerThread->mActiveTracks.indexOf(this) < 0) { reset(); } LOGV("(> STOPPED) => STOPPED (%d)", mName); } } -void AudioFlinger::Track::pause() +void AudioFlinger::MixerThread::Track::pause() { - LOGV("pause(%d)", mName); - Mutex::Autolock _l(mAudioFlinger->mLock); + LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); if (mState == ACTIVE || mState == RESUMING) { mState = PAUSING; LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName); } } -void AudioFlinger::Track::flush() +void AudioFlinger::MixerThread::Track::flush() { LOGV("flush(%d)", mName); - Mutex::Autolock _l(mAudioFlinger->mLock); + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); if (mState != STOPPED && mState != PAUSED && mState != PAUSING) { return; } @@ -1298,7 +1889,7 @@ void AudioFlinger::Track::flush() reset(); } -void AudioFlinger::Track::reset() +void AudioFlinger::MixerThread::Track::reset() { // Do not reset twice to avoid discarding data written just after a flush and before // the audioflinger thread detects the track is stopped. @@ -1313,12 +1904,12 @@ void AudioFlinger::Track::reset() } } -void AudioFlinger::Track::mute(bool muted) +void AudioFlinger::MixerThread::Track::mute(bool muted) { mMute = muted; } -void AudioFlinger::Track::setVolume(float left, float right) +void AudioFlinger::MixerThread::Track::setVolume(float left, float right) { mVolume[0] = left; mVolume[1] = right; @@ -1326,7 +1917,292 @@ void AudioFlinger::Track::setVolume(float left, float right) // ---------------------------------------------------------------------------- -AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::Track>& track) +// RecordTrack constructor must be called with AudioFlinger::mLock held +AudioFlinger::MixerThread::RecordTrack::RecordTrack( + const sp<MixerThread>& mixerThread, + const sp<Client>& client, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags) + : TrackBase(mixerThread, client, streamType, sampleRate, format, + channelCount, frameCount, flags, 0), + mOverflow(false) +{ +} + +AudioFlinger::MixerThread::RecordTrack::~RecordTrack() +{ + Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock); + mMixerThread->deleteTrackName_l(mName); +} + +status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) +{ + audio_track_cblk_t* cblk = this->cblk(); + uint32_t framesAvail; + uint32_t framesReq = buffer->frameCount; + + // Check if last stepServer failed, try to step now + if (mFlags & TrackBase::STEPSERVER_FAILED) { + if (!step()) goto getNextBuffer_exit; + LOGV("stepServer recovered"); + mFlags &= ~TrackBase::STEPSERVER_FAILED; + } + + framesAvail = cblk->framesAvailable_l(); + + if (LIKELY(framesAvail)) { + uint32_t s = cblk->server; + uint32_t bufferEnd = cblk->serverBase + cblk->frameCount; + + if (framesReq > framesAvail) { + framesReq = framesAvail; + } + if (s + framesReq > bufferEnd) { + framesReq = bufferEnd - s; + } + + buffer->raw = getBuffer(s, framesReq); + if (buffer->raw == 0) goto getNextBuffer_exit; + + buffer->frameCount = framesReq; + return NO_ERROR; + } + +getNextBuffer_exit: + buffer->raw = 0; + buffer->frameCount = 0; + return NOT_ENOUGH_DATA; +} + +status_t AudioFlinger::MixerThread::RecordTrack::start() +{ + return mMixerThread->mAudioFlinger->startRecord(this); +} + +void AudioFlinger::MixerThread::RecordTrack::stop() +{ + mMixerThread->mAudioFlinger->stopRecord(this); + TrackBase::reset(); + // Force overerrun condition to avoid false overrun callback until first data is + // read from buffer + mCblk->flowControlFlag = 1; +} + + +// ---------------------------------------------------------------------------- + +AudioFlinger::MixerThread::OutputTrack::OutputTrack( + const sp<MixerThread>& mixerThread, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount) + : Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL), + mOutputMixerThread(mixerThread) +{ + + mCblk->out = 1; + mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); + mCblk->volume[0] = mCblk->volume[1] = 0x1000; + mOutBuffer.frameCount = 0; + mCblk->bufferTimeoutMs = 10; + + LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p", + mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd); + +} + +AudioFlinger::MixerThread::OutputTrack::~OutputTrack() +{ + stop(); +} + +status_t AudioFlinger::MixerThread::OutputTrack::start() +{ + status_t status = Track::start(); + + mRetryCount = 127; + return status; +} + +void AudioFlinger::MixerThread::OutputTrack::stop() +{ + Track::stop(); + clearBufferQueue(); + mOutBuffer.frameCount = 0; +} + +void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames) +{ + Buffer *pInBuffer; + Buffer inBuffer; + uint32_t channels = mCblk->channels; + + inBuffer.frameCount = frames; + inBuffer.i16 = data; + + if (mCblk->user == 0) { + if (mOutputMixerThread->isMusicActive()) { + mCblk->forceReady = 1; + LOGV("OutputTrack::start() force ready"); + } else if (mCblk->frameCount > frames){ + if (mBufferQueue.size() < kMaxOutputTrackBuffers) { + uint32_t startFrames = (mCblk->frameCount - frames); + LOGV("OutputTrack::start() write %d frames", startFrames); + pInBuffer = new Buffer; + pInBuffer->mBuffer = new int16_t[startFrames * channels]; + pInBuffer->frameCount = startFrames; + pInBuffer->i16 = pInBuffer->mBuffer; + memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t)); + mBufferQueue.add(pInBuffer); + } else { + LOGW ("OutputTrack::write() no more buffers"); + } + } + } + + while (1) { + // First write pending buffers, then new data + if (mBufferQueue.size()) { + pInBuffer = mBufferQueue.itemAt(0); + } else { + pInBuffer = &inBuffer; + } + + if (pInBuffer->frameCount == 0) { + break; + } + + if (mOutBuffer.frameCount == 0) { + mOutBuffer.frameCount = pInBuffer->frameCount; + if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) { + break; + } + } + + uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount; + memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t)); + mCblk->stepUser(outFrames); + pInBuffer->frameCount -= outFrames; + pInBuffer->i16 += outFrames * channels; + mOutBuffer.frameCount -= outFrames; + mOutBuffer.i16 += outFrames * channels; + + if (pInBuffer->frameCount == 0) { + if (mBufferQueue.size()) { + mBufferQueue.removeAt(0); + delete [] pInBuffer->mBuffer; + delete pInBuffer; + } else { + break; + } + } + } + + // If we could not write all frames, allocate a buffer and queue it for next time. + if (inBuffer.frameCount) { + if (mBufferQueue.size() < kMaxOutputTrackBuffers) { + pInBuffer = new Buffer; + pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels]; + pInBuffer->frameCount = inBuffer.frameCount; + pInBuffer->i16 = pInBuffer->mBuffer; + memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t)); + mBufferQueue.add(pInBuffer); + } else { + LOGW("OutputTrack::write() no more buffers"); + } + } + + // Calling write() with a 0 length buffer, means that no more data will be written: + // If no more buffers are pending, fill output track buffer to make sure it is started + // by output mixer. + if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) { + frames = mCblk->frameCount - mCblk->user; + pInBuffer = new Buffer; + pInBuffer->mBuffer = new int16_t[frames * channels]; + pInBuffer->frameCount = frames; + pInBuffer->i16 = pInBuffer->mBuffer; + memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t)); + mBufferQueue.add(pInBuffer); + } + +} + +status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer) +{ + int active; + int timeout = 0; + status_t result; + audio_track_cblk_t* cblk = mCblk; + uint32_t framesReq = buffer->frameCount; + + LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server); + buffer->frameCount = 0; + + uint32_t framesAvail = cblk->framesAvailable(); + + if (framesAvail == 0) { + return AudioTrack::NO_MORE_BUFFERS; + } + + if (framesReq > framesAvail) { + framesReq = framesAvail; + } + + uint32_t u = cblk->user; + uint32_t bufferEnd = cblk->userBase + cblk->frameCount; + + if (u + framesReq > bufferEnd) { + framesReq = bufferEnd - u; + } + + buffer->frameCount = framesReq; + buffer->raw = (void *)cblk->buffer(u); + return NO_ERROR; +} + + +void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue() +{ + size_t size = mBufferQueue.size(); + Buffer *pBuffer; + + for (size_t i = 0; i < size; i++) { + pBuffer = mBufferQueue.itemAt(i); + delete [] pBuffer->mBuffer; + delete pBuffer; + } + mBufferQueue.clear(); +} + +// ---------------------------------------------------------------------------- + +AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid) + : RefBase(), + mAudioFlinger(audioFlinger), + mMemoryDealer(new MemoryDealer(1024*1024)), + mPid(pid) +{ + // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer +} + +AudioFlinger::Client::~Client() +{ + mAudioFlinger->removeClient(mPid); +} + +const sp<MemoryDealer>& AudioFlinger::Client::heap() const +{ + return mMemoryDealer; +} + +// ---------------------------------------------------------------------------- + +AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track) : BnAudioTrack(), mTrack(track) { @@ -1386,8 +2262,7 @@ sp<IAudioRecord> AudioFlinger::openRecord( uint32_t flags, status_t *status) { - sp<AudioRecordThread> thread; - sp<RecordTrack> recordTrack; + sp<MixerThread::RecordTrack> recordTrack; sp<RecordHandle> recordHandle; sp<Client> client; wp<Client> wclient; @@ -1414,12 +2289,6 @@ sp<IAudioRecord> AudioFlinger::openRecord( goto Exit; } - if (mSampleRate == 0) { - LOGE("Audio driver not initialized"); - lStatus = NO_INIT; - goto Exit; - } - if (mAudioRecordThread == 0) { LOGE("Audio record thread not started"); lStatus = NO_INIT; @@ -1436,7 +2305,7 @@ sp<IAudioRecord> AudioFlinger::openRecord( } // add client to list - { + { // scope for mLock Mutex::Autolock _l(mLock); wclient = mClients.valueFor(pid); if (wclient != NULL) { @@ -1445,15 +2314,20 @@ sp<IAudioRecord> AudioFlinger::openRecord( client = new Client(this, pid); mClients.add(pid, client); } - } - // frameCount must be a multiple of input buffer size - inFrameCount = inputBufferSize/channelCount/sizeof(short); - frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount; - - // create new record track and pass to record thread - recordTrack = new RecordTrack(this, client, streamType, sampleRate, - format, channelCount, frameCount); + // frameCount must be a multiple of input buffer size + inFrameCount = inputBufferSize/channelCount/sizeof(short); + frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount; + + // create new record track. The record track uses one track in mHardwareMixerThread by convention. + recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate, + format, channelCount, frameCount, flags); + } + if (recordTrack->getCblk() == NULL) { + recordTrack.clear(); + lStatus = NO_MEMORY; + goto Exit; + } // return to handle to client recordHandle = new RecordHandle(recordTrack); @@ -1466,97 +2340,22 @@ Exit: return recordHandle; } -status_t AudioFlinger::startRecord(RecordTrack* recordTrack) { +status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) { if (mAudioRecordThread != 0) { return mAudioRecordThread->start(recordTrack); } return NO_INIT; } -void AudioFlinger::stopRecord(RecordTrack* recordTrack) { +void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) { if (mAudioRecordThread != 0) { mAudioRecordThread->stop(recordTrack); } } - -// ---------------------------------------------------------------------------- - -AudioFlinger::RecordTrack::RecordTrack( - const sp<AudioFlinger>& audioFlinger, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount) - : TrackBase(audioFlinger, client, streamType, sampleRate, format, - channelCount, frameCount, 0), - mOverflow(false) -{ -} - -AudioFlinger::RecordTrack::~RecordTrack() -{ - mAudioFlinger->audioMixer()->deleteTrackName(mName); -} - -status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) -{ - audio_track_cblk_t* cblk = this->cblk(); - uint32_t framesAvail; - uint32_t framesReq = buffer->frameCount; - - // Check if last stepServer failed, try to step now - if (mFlags & TrackBase::STEPSERVER_FAILED) { - if (!step()) goto getNextBuffer_exit; - LOGV("stepServer recovered"); - mFlags &= ~TrackBase::STEPSERVER_FAILED; - } - - framesAvail = cblk->framesAvailable_l(); - - if (LIKELY(framesAvail)) { - uint32_t s = cblk->server; - uint32_t bufferEnd = cblk->serverBase + cblk->frameCount; - - if (framesReq > framesAvail) { - framesReq = framesAvail; - } - if (s + framesReq > bufferEnd) { - framesReq = bufferEnd - s; - } - - buffer->raw = getBuffer(s, framesReq); - if (buffer->raw == 0) goto getNextBuffer_exit; - - buffer->frameCount = framesReq; - return NO_ERROR; - } - -getNextBuffer_exit: - buffer->raw = 0; - buffer->frameCount = 0; - return NOT_ENOUGH_DATA; -} - -status_t AudioFlinger::RecordTrack::start() -{ - return mAudioFlinger->startRecord(this); -} - -void AudioFlinger::RecordTrack::stop() -{ - mAudioFlinger->stopRecord(this); - TrackBase::reset(); - // Force overerrun condition to avoid false overrun callback until first data is - // read from buffer - mCblk->flowControlFlag = 1; -} - // ---------------------------------------------------------------------------- -AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordTrack>& recordTrack) +AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack) : BnAudioRecord(), mRecordTrack(recordTrack) { @@ -1588,8 +2387,10 @@ status_t AudioFlinger::RecordHandle::onTransact( // ---------------------------------------------------------------------------- -AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware) : +AudioFlinger::AudioRecordThread::AudioRecordThread(AudioHardwareInterface* audioHardware, + const sp<AudioFlinger>& audioFlinger) : mAudioHardware(audioHardware), + mAudioFlinger(audioFlinger), mActive(false) { } @@ -1619,15 +2420,17 @@ bool AudioFlinger::AudioRecordThread::threadLoop() input = 0; } mRecordTrack.clear(); + mStopped.signal(); mWaitWorkCV.wait(mLock); LOGV("AudioRecordThread: loop starting"); if (mRecordTrack != 0) { input = mAudioHardware->openInputStream(mRecordTrack->format(), - mRecordTrack->channelCount(), - mRecordTrack->sampleRate(), - &mStartStatus); + mRecordTrack->channelCount(), + mRecordTrack->sampleRate(), + &mStartStatus, + (AudioSystem::audio_in_acoustics)(mRecordTrack->mFlags >> 16)); if (input != 0) { inBufferSize = input->bufferSize(); inFrameCount = inBufferSize/input->frameSize(); @@ -1643,12 +2446,14 @@ bool AudioFlinger::AudioRecordThread::threadLoop() mWaitWorkCV.signal(); } mLock.unlock(); - } else if (mRecordTrack != 0){ + } else if (mRecordTrack != 0) { buffer.frameCount = inFrameCount; - if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) { + if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR && + (int)buffer.frameCount == inFrameCount)) { LOGV("AudioRecordThread read: %d frames", buffer.frameCount); - if (input->read(buffer.raw, inBufferSize) < 0) { + ssize_t bytesRead = input->read(buffer.raw, inBufferSize); + if (bytesRead < 0) { LOGE("Error reading audio input"); sleep(1); } @@ -1677,7 +2482,7 @@ bool AudioFlinger::AudioRecordThread::threadLoop() return false; } -status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack) +status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack) { LOGV("AudioRecordThread::start"); AutoMutex lock(&mLock); @@ -1690,6 +2495,19 @@ status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack) mRecordTrack = recordTrack; +#ifdef WITH_A2DP + { // scope for lock2 + + // AudioFlinger::mLock must be locked before calling + // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). + AutoMutex lock2(&mAudioFlinger->mLock); + + // Currently there is no way to detect if we are recording over SCO, + // so we disable A2DP during any recording. + mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED); + } +#endif + // signal thread to start LOGV("Signal record thread"); mWaitWorkCV.signal(); @@ -1698,11 +2516,24 @@ status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack) return mStartStatus; } -void AudioFlinger::AudioRecordThread::stop(RecordTrack* recordTrack) { +void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) { LOGV("AudioRecordThread::stop"); AutoMutex lock(&mLock); if (mActive && (recordTrack == mRecordTrack.get())) { +#ifdef WITH_A2DP + { // scope for lock2 + + // AudioFlinger::mLock must be locked before calling + // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). + AutoMutex lock2(&mAudioFlinger->mLock); + + // Currently there is no way to detect if we are recording over SCO, + // so we disable A2DP during any recording. + mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED); + } +#endif mActive = false; + mStopped.wait(mLock); } } @@ -1717,6 +2548,22 @@ void AudioFlinger::AudioRecordThread::exit() requestExitAndWait(); } +status_t AudioFlinger::AudioRecordThread::dump(int fd, const Vector<String16>& args) +{ + const size_t SIZE = 256; + char buffer[SIZE]; + String8 result; + pid_t pid = 0; + + if (mRecordTrack != 0 && mRecordTrack->mClient != 0) { + snprintf(buffer, SIZE, "Record client pid: %d\n", mRecordTrack->mClient->pid()); + result.append(buffer); + } else { + result.append("No record client\n"); + } + write(fd, result.string(), result.size()); + return NO_ERROR; +} status_t AudioFlinger::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 9ab362a39d..ab15947f86 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -22,6 +22,7 @@ #include <sys/types.h> #include <media/IAudioFlinger.h> +#include <media/IAudioFlingerClient.h> #include <media/IAudioTrack.h> #include <media/IAudioRecord.h> #include <media/AudioTrack.h> @@ -32,6 +33,7 @@ #include <utils/MemoryDealer.h> #include <utils/KeyedVector.h> #include <utils/SortedVector.h> +#include <utils/Vector.h> #include <hardware_legacy/AudioHardwareInterface.h> @@ -54,18 +56,13 @@ class AudioBuffer; static const nsecs_t kStandbyTimeInNsecs = seconds(3); -class AudioFlinger : public BnAudioFlinger, protected Thread +class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient { public: static void instantiate(); virtual status_t dump(int fd, const Vector<String16>& args); - // Thread virtuals - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void onFirstRef(); - // IAudioFlinger interface virtual sp<IAudioTrack> createTrack( pid_t pid, @@ -78,11 +75,11 @@ public: const sp<IMemory>& sharedBuffer, status_t *status); - virtual uint32_t sampleRate() const; - virtual int channelCount() const; - virtual int format() const; - virtual size_t frameCount() const; - virtual size_t latency() const; + virtual uint32_t sampleRate(int output) const; + virtual int channelCount(int output) const; + virtual int format(int output) const; + virtual size_t frameCount(int output) const; + virtual uint32_t latency(int output) const; virtual status_t setMasterVolume(float value); virtual status_t setMasterMute(bool muted); @@ -107,8 +104,19 @@ public: virtual bool isMusicActive() const; + virtual bool isA2dpEnabled() const; + virtual status_t setParameter(const char* key, const char* value); + virtual void registerClient(const sp<IAudioFlingerClient>& client); + + virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); + + virtual void wakeUp() { mWaitWorkCV.broadcast(); } + + // IBinder::DeathRecipient + virtual void binderDied(const wp<IBinder>& who); + enum hardware_call_state { AUDIO_HW_IDLE = 0, AUDIO_HW_INIT, @@ -149,23 +157,31 @@ private: AudioFlinger(); virtual ~AudioFlinger(); - void setOutput(AudioStreamOut* output); - void doSetOutput(AudioStreamOut* output); - size_t getOutputFrameCount(AudioStreamOut* output); + void setOutput(int outputType); + void doSetOutput(int outputType); #ifdef WITH_A2DP + void setA2dpEnabled_l(bool enable); + void checkA2dpEnabledChange_l(); +#endif + static bool streamForcedToSpeaker(int streamType); static bool streamDisablesA2dp(int streamType); - inline bool isA2dpEnabled() const { - return (mRequestedOutput == mA2dpOutput || - (mOutput && mOutput == mA2dpOutput)); - } - void setA2dpEnabled(bool enable); + + // Management of forced route to speaker for certain track types. + enum force_speaker_command { + ACTIVE_TRACK_ADDED = 0, + ACTIVE_TRACK_REMOVED, + CHECK_ROUTE_RESTORE_TIME, + FORCE_ROUTE_RESTORE + }; + void handleForcedSpeakerRoute(int command); +#ifdef WITH_A2DP + void handleStreamDisablesA2dp_l(int command); #endif // Internal dump utilites. status_t dumpPermissionDenial(int fd, const Vector<String16>& args); status_t dumpClients(int fd, const Vector<String16>& args); - status_t dumpTracks(int fd, const Vector<String16>& args); status_t dumpInternals(int fd, const Vector<String16>& args); // --- Client --- @@ -184,168 +200,347 @@ private: }; - // --- Track --- class TrackHandle; class RecordHandle; class AudioRecordThread; - // base for record and playback - class TrackBase : public AudioBufferProvider, public RefBase { - + + // --- MixerThread --- + class MixerThread : public Thread { public: - enum track_state { - IDLE, - TERMINATED, - STOPPED, - RESUMING, - ACTIVE, - PAUSING, - PAUSED + + // --- Track --- + + // base for record and playback + class TrackBase : public AudioBufferProvider, public RefBase { + + public: + enum track_state { + IDLE, + TERMINATED, + STOPPED, + RESUMING, + ACTIVE, + PAUSING, + PAUSED + }; + + enum track_flags { + STEPSERVER_FAILED = 0x01, // StepServer could not acquire cblk->lock mutex + SYSTEM_FLAGS_MASK = 0x0000ffffUL, + // The upper 16 bits are used for track-specific flags. + }; + + TrackBase(const sp<MixerThread>& mixerThread, + const sp<Client>& client, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags, + const sp<IMemory>& sharedBuffer); + ~TrackBase(); + + virtual status_t start() = 0; + virtual void stop() = 0; + sp<IMemory> getCblk() const; + + protected: + friend class MixerThread; + friend class RecordHandle; + friend class AudioRecordThread; + + TrackBase(const TrackBase&); + TrackBase& operator = (const TrackBase&); + + virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0; + virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); + + audio_track_cblk_t* cblk() const { + return mCblk; + } + + int type() const { + return mStreamType; + } + + int format() const { + return mFormat; + } + + int channelCount() const ; + + int sampleRate() const; + + void* getBuffer(uint32_t offset, uint32_t frames) const; + + int name() const { + return mName; + } + + bool isStopped() const { + return mState == STOPPED; + } + + bool isTerminated() const { + return mState == TERMINATED; + } + + bool step(); + void reset(); + + sp<MixerThread> mMixerThread; + sp<Client> mClient; + sp<IMemory> mCblkMemory; + audio_track_cblk_t* mCblk; + int mStreamType; + void* mBuffer; + void* mBufferEnd; + uint32_t mFrameCount; + int mName; + // we don't really need a lock for these + int mState; + int mClientTid; + uint8_t mFormat; + uint32_t mFlags; }; - enum track_flags { - STEPSERVER_FAILED = 0x01 // StepServer could not acquire cblk->lock mutex + // playback track + class Track : public TrackBase { + public: + Track( const sp<MixerThread>& mixerThread, + const sp<Client>& client, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + const sp<IMemory>& sharedBuffer); + ~Track(); + + void dump(char* buffer, size_t size); + virtual status_t start(); + virtual void stop(); + void pause(); + + void flush(); + void destroy(); + void mute(bool); + void setVolume(float left, float right); + + protected: + friend class MixerThread; + friend class AudioFlinger; + friend class AudioFlinger::TrackHandle; + + Track(const Track&); + Track& operator = (const Track&); + + virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); + + bool isMuted() const { + return (mMute || mMixerThread->mStreamTypes[mStreamType].mute); + } + + bool isPausing() const { + return mState == PAUSING; + } + + bool isPaused() const { + return mState == PAUSED; + } + + bool isReady() const; + + void setPaused() { mState = PAUSED; } + void reset(); + + // we don't really need a lock for these + float mVolume[2]; + volatile bool mMute; + // FILLED state is used for suppressing volume ramp at begin of playing + enum {FS_FILLING, FS_FILLED, FS_ACTIVE}; + mutable uint8_t mFillingUpStatus; + int8_t mRetryCount; + sp<IMemory> mSharedBuffer; + bool mResetDone; + }; // end of Track + + // record track + class RecordTrack : public TrackBase { + public: + RecordTrack(const sp<MixerThread>& mixerThread, + const sp<Client>& client, + int streamType, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount, + uint32_t flags); + ~RecordTrack(); + + virtual status_t start(); + virtual void stop(); + + bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; } + bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; } + + private: + friend class AudioFlinger; + friend class AudioFlinger::RecordHandle; + friend class AudioFlinger::AudioRecordThread; + friend class MixerThread; + + RecordTrack(const Track&); + RecordTrack& operator = (const Track&); + + virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); + + bool mOverflow; }; - TrackBase( const sp<AudioFlinger>& audioFlinger, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount, - const sp<IMemory>& sharedBuffer); - ~TrackBase(); - - virtual status_t start() = 0; - virtual void stop() = 0; - sp<IMemory> getCblk() const; - - protected: - friend class AudioFlinger; - friend class RecordHandle; - friend class AudioRecordThread; - - TrackBase(const TrackBase&); - TrackBase& operator = (const TrackBase&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0; - virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); - - audio_track_cblk_t* cblk() const { - return mCblk; - } - - int type() const { - return mStreamType; - } - - int format() const { - return mFormat; - } - - int channelCount() const ; - - int sampleRate() const; - - void* getBuffer(uint32_t offset, uint32_t frames) const; - - int name() const { - return mName; - } - - bool isStopped() const { - return mState == STOPPED; - } - - bool isTerminated() const { - return mState == TERMINATED; - } - - bool step(); - void reset(); - - sp<AudioFlinger> mAudioFlinger; - sp<Client> mClient; - sp<IMemory> mCblkMemory; - audio_track_cblk_t* mCblk; - int mStreamType; - void* mBuffer; - void* mBufferEnd; - uint32_t mFrameCount; - int mName; - // we don't really need a lock for these - int mState; - int mClientTid; - uint8_t mFormat; - uint8_t mFlags; - }; - - // playback track - class Track : public TrackBase { - public: - Track( const sp<AudioFlinger>& audioFlinger, - const sp<Client>& client, + // playback track + class OutputTrack : public Track { + public: + + class Buffer: public AudioBufferProvider::Buffer { + public: + int16_t *mBuffer; + }; + + OutputTrack( const sp<MixerThread>& mixerThread, + uint32_t sampleRate, + int format, + int channelCount, + int frameCount); + ~OutputTrack(); + + virtual status_t start(); + virtual void stop(); + void write(int16_t* data, uint32_t frames); + bool bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; } + + private: + + status_t obtainBuffer(AudioBufferProvider::Buffer* buffer); + void clearBufferQueue(); + + sp<MixerThread> mOutputMixerThread; + Vector < Buffer* > mBufferQueue; + AudioBufferProvider::Buffer mOutBuffer; + uint32_t mFramesWritten; + + }; // end of OutputTrack + + MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType); + virtual ~MixerThread(); + + virtual status_t dump(int fd, const Vector<String16>& args); + + // Thread virtuals + virtual bool threadLoop(); + virtual status_t readyToRun(); + virtual void onFirstRef(); + + virtual uint32_t sampleRate() const; + virtual int channelCount() const; + virtual int format() const; + virtual size_t frameCount() const; + virtual uint32_t latency() const; + + virtual status_t setMasterVolume(float value); + virtual status_t setMasterMute(bool muted); + + virtual float masterVolume() const; + virtual bool masterMute() const; + + virtual status_t setStreamVolume(int stream, float value); + virtual status_t setStreamMute(int stream, bool muted); + + virtual float streamVolume(int stream) const; + virtual bool streamMute(int stream) const; + + bool isMusicActive() const; + + + sp<Track> createTrack_l( + const sp<AudioFlinger::Client>& client, int streamType, uint32_t sampleRate, int format, int channelCount, int frameCount, - const sp<IMemory>& sharedBuffer); - ~Track(); - - void dump(char* buffer, size_t size); - virtual status_t start(); - virtual void stop(); - void pause(); - - void flush(); - void destroy(); - void mute(bool); - void setVolume(float left, float right); + const sp<IMemory>& sharedBuffer, + status_t *status); + + void getTracks_l(SortedVector < sp<Track> >& tracks, + SortedVector < wp<Track> >& activeTracks); + void putTracks_l(SortedVector < sp<Track> >& tracks, + SortedVector < wp<Track> >& activeTracks); + void setOuputTrack(OutputTrack *track) { mOutputTrack = track; } + + struct stream_type_t { + stream_type_t() + : volume(1.0f), + mute(false) + { + } + float volume; + bool mute; + }; private: - friend class AudioFlinger; - friend class TrackHandle; - - Track(const Track&); - Track& operator = (const Track&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); - - bool isMuted() const { - return mMute; - } - - bool isPausing() const { - return mState == PAUSING; - } - bool isPaused() const { - return mState == PAUSED; - } - bool isReady() const; - - void setPaused() { mState = PAUSED; } - void reset(); - - // we don't really need a lock for these - float mVolume[2]; - volatile bool mMute; - // FILLED state is used for suppressing volume ramp at begin of playing - enum {FS_FILLING, FS_FILLED, FS_ACTIVE}; - mutable uint8_t mFillingUpStatus; - int8_t mRetryCount; - sp<IMemory> mSharedBuffer; - bool mResetDone; - }; // end of Track + friend class AudioFlinger; + friend class Track; + friend class TrackBase; + friend class RecordTrack; + + MixerThread(const Client&); + MixerThread& operator = (const MixerThread&); + + status_t addTrack_l(const sp<Track>& track); + void removeTrack_l(wp<Track> track, int name); + void destroyTrack_l(const sp<Track>& track); + int getTrackName_l(); + void deleteTrackName_l(int name); + void addActiveTrack_l(const wp<Track>& t); + void removeActiveTrack_l(const wp<Track>& t); + size_t getOutputFrameCount(); + + status_t dumpInternals(int fd, const Vector<String16>& args); + status_t dumpTracks(int fd, const Vector<String16>& args); + + sp<AudioFlinger> mAudioFlinger; + SortedVector< wp<Track> > mActiveTracks; + SortedVector< sp<Track> > mTracks; + stream_type_t mStreamTypes[AudioSystem::NUM_STREAM_TYPES]; + AudioMixer* mAudioMixer; + AudioStreamOut* mOutput; + int mOutputType; + uint32_t mSampleRate; + size_t mFrameCount; + int mChannelCount; + int mFormat; + int16_t* mMixBuffer; + float mMasterVolume; + bool mMasterMute; + nsecs_t mLastWriteTime; + int mNumWrites; + int mNumDelayedWrites; + bool mStandby; + bool mInWrite; + sp <OutputTrack> mOutputTrack; + }; + friend class AudioBuffer; class TrackHandle : public android::BnAudioTrack { public: - TrackHandle(const sp<Track>& track); + TrackHandle(const sp<MixerThread::Track>& track); virtual ~TrackHandle(); virtual status_t start(); virtual void stop(); @@ -357,70 +552,20 @@ private: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); private: - sp<Track> mTrack; - }; - - struct stream_type_t { - stream_type_t() - : volume(1.0f), - mute(false) - { - } - float volume; - bool mute; + sp<MixerThread::Track> mTrack; }; friend class Client; - friend class Track; + friend class MixerThread::Track; void removeClient(pid_t pid); - status_t addTrack(const sp<Track>& track); - void removeTrack(wp<Track> track, int name); - void remove_track_l(wp<Track> track, int name); - void destroyTrack(const sp<Track>& track); - void addActiveTrack(const wp<Track>& track); - void removeActiveTrack(const wp<Track>& track); - AudioMixer* audioMixer() { - return mAudioMixer; - } - - // record track - class RecordTrack : public TrackBase { - public: - RecordTrack( const sp<AudioFlinger>& audioFlinger, - const sp<Client>& client, - int streamType, - uint32_t sampleRate, - int format, - int channelCount, - int frameCount); - ~RecordTrack(); - - virtual status_t start(); - virtual void stop(); - - bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; } - bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; } - - private: - friend class AudioFlinger; - friend class RecordHandle; - friend class AudioRecordThread; - - RecordTrack(const Track&); - RecordTrack& operator = (const Track&); - - virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); - - bool mOverflow; - }; class RecordHandle : public android::BnAudioRecord { public: - RecordHandle(const sp<RecordTrack>& recordTrack); + RecordHandle(const sp<MixerThread::RecordTrack>& recordTrack); virtual ~RecordHandle(); virtual status_t start(); virtual void stop(); @@ -428,72 +573,66 @@ private: virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); private: - sp<RecordTrack> mRecordTrack; + sp<MixerThread::RecordTrack> mRecordTrack; }; // record thread class AudioRecordThread : public Thread { public: - AudioRecordThread(AudioHardwareInterface* audioHardware); + AudioRecordThread(AudioHardwareInterface* audioHardware, const sp<AudioFlinger>& audioFlinger); virtual ~AudioRecordThread(); virtual bool threadLoop(); virtual status_t readyToRun() { return NO_ERROR; } virtual void onFirstRef() {} - status_t start(RecordTrack* recordTrack); - void stop(RecordTrack* recordTrack); + status_t start(MixerThread::RecordTrack* recordTrack); + void stop(MixerThread::RecordTrack* recordTrack); void exit(); + status_t dump(int fd, const Vector<String16>& args); private: AudioRecordThread(); AudioHardwareInterface *mAudioHardware; - sp<RecordTrack> mRecordTrack; + sp<AudioFlinger> mAudioFlinger; + sp<MixerThread::RecordTrack> mRecordTrack; Mutex mLock; Condition mWaitWorkCV; + Condition mStopped; volatile bool mActive; status_t mStartStatus; }; friend class AudioRecordThread; + friend class MixerThread; + + status_t startRecord(MixerThread::RecordTrack* recordTrack); + void stopRecord(MixerThread::RecordTrack* recordTrack); - status_t startRecord(RecordTrack* recordTrack); - void stopRecord(RecordTrack* recordTrack); + mutable Mutex mHardwareLock; + mutable Mutex mLock; + mutable Condition mWaitWorkCV; - mutable Mutex mHardwareLock; - mutable Mutex mLock; - mutable Condition mWaitWorkCV; DefaultKeyedVector< pid_t, wp<Client> > mClients; - SortedVector< wp<Track> > mActiveTracks; - SortedVector< sp<Track> > mTracks; - float mMasterVolume; - uint32_t mMasterRouting; - bool mMasterMute; - stream_type_t mStreamTypes[AudioTrack::NUM_STREAM_TYPES]; - - AudioMixer* mHardwareAudioMixer; - AudioMixer* mA2dpAudioMixer; - AudioMixer* mAudioMixer; + + sp<MixerThread> mA2dpMixerThread; + sp<MixerThread> mHardwareMixerThread; AudioHardwareInterface* mAudioHardware; AudioHardwareInterface* mA2dpAudioInterface; - AudioStreamOut* mHardwareOutput; - AudioStreamOut* mA2dpOutput; - AudioStreamOut* mOutput; - AudioStreamOut* mRequestedOutput; sp<AudioRecordThread> mAudioRecordThread; - uint32_t mSampleRate; - size_t mFrameCount; - int mChannelCount; - int mFormat; - int16_t* mMixBuffer; + bool mA2dpEnabled; + bool mNotifyA2dpChange; mutable int mHardwareStatus; - nsecs_t mLastWriteTime; - int mNumWrites; - int mNumDelayedWrites; - bool mStandby; - bool mInWrite; + SortedVector< wp<IBinder> > mNotificationClients; + int mForcedSpeakerCount; int mA2dpDisableCount; + + // true if A2DP should resume when mA2dpDisableCount returns to zero bool mA2dpSuppressed; + uint32_t mSavedRoute; + uint32_t mForcedRoute; + nsecs_t mRouteRestoreTime; + bool mMusicMuteSaved; }; // ---------------------------------------------------------------------------- diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp index e455186ecf..62beadabdd 100644 --- a/libs/audioflinger/AudioHardwareGeneric.cpp +++ b/libs/audioflinger/AudioHardwareGeneric.cpp @@ -93,7 +93,8 @@ void AudioHardwareGeneric::closeOutputStream(AudioStreamOutGeneric* out) { } AudioStreamIn* AudioHardwareGeneric::openInputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) + int format, int channelCount, uint32_t sampleRate, status_t *status, + AudioSystem::audio_in_acoustics acoustics) { AutoMutex lock(mLock); @@ -107,7 +108,7 @@ AudioStreamIn* AudioHardwareGeneric::openInputStream( // create new output stream AudioStreamInGeneric* in = new AudioStreamInGeneric(); - status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate); + status_t lStatus = in->set(this, mFd, format, channelCount, sampleRate, acoustics); if (status) { *status = lStatus; } @@ -246,7 +247,8 @@ status_t AudioStreamInGeneric::set( int fd, int format, int channels, - uint32_t rate) + uint32_t rate, + AudioSystem::audio_in_acoustics acoustics) { // FIXME: remove logging LOGD("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, format, channels, rate); diff --git a/libs/audioflinger/AudioHardwareGeneric.h b/libs/audioflinger/AudioHardwareGeneric.h index a7822e11ae..c949aa12a4 100644 --- a/libs/audioflinger/AudioHardwareGeneric.h +++ b/libs/audioflinger/AudioHardwareGeneric.h @@ -47,7 +47,7 @@ public: virtual size_t bufferSize() const { return 4096; } virtual int channelCount() const { return 2; } virtual int format() const { return AudioSystem::PCM_16_BIT; } - virtual uint32_t latency() const { return 0; } + virtual uint32_t latency() const { return 20; } virtual status_t setVolume(float volume) { return INVALID_OPERATION; } virtual ssize_t write(const void* buffer, size_t bytes); virtual status_t standby(); @@ -69,7 +69,8 @@ public: int mFd, int format, int channelCount, - uint32_t sampleRate); + uint32_t sampleRate, + AudioSystem::audio_in_acoustics acoustics); uint32_t sampleRate() const { return 8000; } virtual size_t bufferSize() const { return 320; } @@ -114,7 +115,8 @@ public: int format, int channelCount, uint32_t sampleRate, - status_t *status); + status_t *status, + AudioSystem::audio_in_acoustics acoustics); void closeOutputStream(AudioStreamOutGeneric* out); void closeInputStream(AudioStreamInGeneric* in); diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp index e9f3d690f6..b13cb1c072 100644 --- a/libs/audioflinger/AudioHardwareStub.cpp +++ b/libs/audioflinger/AudioHardwareStub.cpp @@ -56,10 +56,11 @@ AudioStreamOut* AudioHardwareStub::openOutputStream( } AudioStreamIn* AudioHardwareStub::openInputStream( - int format, int channelCount, uint32_t sampleRate, status_t *status) + int format, int channelCount, uint32_t sampleRate, + status_t *status, AudioSystem::audio_in_acoustics acoustics) { AudioStreamInStub* in = new AudioStreamInStub(); - status_t lStatus = in->set(format, channelCount, sampleRate); + status_t lStatus = in->set(format, channelCount, sampleRate, acoustics); if (status) { *status = lStatus; } @@ -142,7 +143,8 @@ status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args) // ---------------------------------------------------------------------------- -status_t AudioStreamInStub::set(int format, int channels, uint32_t rate) +status_t AudioStreamInStub::set(int format, int channels, uint32_t rate, + AudioSystem::audio_in_acoustics acoustics) { if ((format == AudioSystem::PCM_16_BIT) && (channels == channelCount()) && diff --git a/libs/audioflinger/AudioHardwareStub.h b/libs/audioflinger/AudioHardwareStub.h index 24736eda68..d40642465b 100644 --- a/libs/audioflinger/AudioHardwareStub.h +++ b/libs/audioflinger/AudioHardwareStub.h @@ -43,7 +43,7 @@ public: class AudioStreamInStub : public AudioStreamIn { public: - virtual status_t set(int format, int channelCount, uint32_t sampleRate); + virtual status_t set(int format, int channelCount, uint32_t sampleRate, AudioSystem::audio_in_acoustics acoustics); virtual uint32_t sampleRate() const { return 8000; } virtual size_t bufferSize() const { return 320; } virtual int channelCount() const { return 1; } @@ -81,7 +81,8 @@ public: int format, int channelCount, uint32_t sampleRate, - status_t *status); + status_t *status, + AudioSystem::audio_in_acoustics acoustics); protected: virtual status_t doRouting() { return NO_ERROR; } diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk index d14cebf5db..496e2717fb 100644 --- a/libs/surfaceflinger/Android.mk +++ b/libs/surfaceflinger/Android.mk @@ -15,8 +15,8 @@ LOCAL_SRC_FILES:= \ LayerBlur.cpp \ LayerBitmap.cpp \ LayerDim.cpp \ - LayerScreenshot.cpp \ - RFBServer.cpp \ + LayerOrientationAnim.cpp \ + OrientationAnimation.cpp \ SurfaceFlinger.cpp \ Tokenizer.cpp \ Transform.cpp \ @@ -38,7 +38,8 @@ LOCAL_SHARED_LIBRARIES := \ libcorecg \ libsgl \ libpixelflinger \ - libGLES_CM + libEGL \ + libGLESv1_CM LOCAL_C_INCLUDES := \ $(call include-path-for, corecg graphics) diff --git a/libs/surfaceflinger/BootAnimation.cpp b/libs/surfaceflinger/BootAnimation.cpp index d18f59abac..2b30336b78 100644 --- a/libs/surfaceflinger/BootAnimation.cpp +++ b/libs/surfaceflinger/BootAnimation.cpp @@ -39,7 +39,9 @@ #include <core/SkBitmap.h> #include <images/SkImageDecoder.h> -#include <GLES/egl.h> +#include <GLES/gl.h> +#include <GLES/glext.h> +#include <EGL/eglext.h> #include "BootAnimation.h" @@ -47,32 +49,28 @@ namespace android { // --------------------------------------------------------------------------- -BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) -: Thread(false) -{ +BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) : + Thread(false) { mSession = SurfaceComposerClient::clientForConnection( composer->createConnection()->asBinder()); } -BootAnimation::~BootAnimation() -{ +BootAnimation::~BootAnimation() { } -void BootAnimation::onFirstRef() -{ +void BootAnimation::onFirstRef() { run("BootAnimation", PRIORITY_DISPLAY); } -const sp<SurfaceComposerClient>& BootAnimation::session() const -{ +const sp<SurfaceComposerClient>& BootAnimation::session() const { return mSession; } -status_t BootAnimation::initTexture( - Texture* texture, AssetManager& assets, const char* name) -{ +status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets, + const char* name) { Asset* asset = assets.open(name, Asset::ACCESS_BUFFER); - if (!asset) return NO_INIT; + if (!asset) + return NO_INIT; SkBitmap bitmap; SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(), &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode); @@ -84,32 +82,32 @@ status_t BootAnimation::initTexture( bitmap.lockPixels(); const int w = bitmap.width(); - const int h = bitmap.height(); + const int h = bitmap.height(); const void* p = bitmap.getPixels(); - + GLint crop[4] = { 0, h, w, -h }; texture->w = w; texture->h = h; glGenTextures(1, &texture->name); glBindTexture(GL_TEXTURE_2D, texture->name); - - switch(bitmap.getConfig()) { + + switch (bitmap.getConfig()) { case SkBitmap::kA8_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, - GL_ALPHA, GL_UNSIGNED_BYTE, p); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, + GL_UNSIGNED_BYTE, p); break; case SkBitmap::kARGB_4444_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, - GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, p); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, + GL_UNSIGNED_SHORT_4_4_4_4, p); break; case SkBitmap::kARGB_8888_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, - GL_RGBA, GL_UNSIGNED_BYTE, p); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, + GL_UNSIGNED_BYTE, p); break; case SkBitmap::kRGB_565_Config: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, p); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, p); break; default: break; @@ -123,8 +121,7 @@ status_t BootAnimation::initTexture( return NO_ERROR; } -status_t BootAnimation::readyToRun() -{ +status_t BootAnimation::readyToRun() { mAssets.addDefaultAssets(); DisplayInfo dinfo; @@ -133,32 +130,27 @@ status_t BootAnimation::readyToRun() return -1; // create the native surface - sp<Surface> s = session()->createSurface(getpid(), 0, - dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565); + sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h, + PIXEL_FORMAT_RGB_565); session()->openTransaction(); s->setLayer(0x40000000); session()->closeTransaction(); // initialize opengl and egl - const EGLint attribs[] = { - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, - EGL_DEPTH_SIZE, 0, - EGL_NONE - }; + const EGLint attribs[] = { EGL_RED_SIZE, 5, EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint w, h, dummy; EGLint numConfigs; EGLConfig config; EGLSurface surface; EGLContext context; EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(display, NULL, NULL); eglChooseConfig(display, attribs, &config, 1, &numConfigs); - surface = eglCreateWindowSurface( - display, config, new EGLNativeWindowSurface(s), NULL); - + mNativeWindowSurface = new EGLNativeWindowSurface(s); + surface = eglCreateWindowSurface(display, config, + mNativeWindowSurface.get(), NULL); + context = eglCreateContext(display, config, NULL, NULL); eglQuerySurface(display, surface, EGL_WIDTH, &w); eglQuerySurface(display, surface, EGL_HEIGHT, &h); @@ -167,7 +159,7 @@ status_t BootAnimation::readyToRun() mContext = context; mSurface = surface; mWidth = w; - mHeight= h; + mHeight = h; mFlingerSurface = s; // initialize GL @@ -180,25 +172,21 @@ status_t BootAnimation::readyToRun() return NO_ERROR; } -void BootAnimation::requestExit() -{ +void BootAnimation::requestExit() { mBarrier.open(); Thread::requestExit(); } -bool BootAnimation::threadLoop() -{ +bool BootAnimation::threadLoop() { bool r = android(); - eglMakeCurrent(mDisplay, 0, 0, 0); - eglDestroyContext(mDisplay, mContext); + eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(mDisplay, mContext); eglDestroySurface(mDisplay, mSurface); - eglTerminate(mDisplay); + mNativeWindowSurface.clear(); return r; } - -bool BootAnimation::android() -{ +bool BootAnimation::android() { initTexture(&mAndroid[0], mAssets, "images/android_320x480.png"); initTexture(&mAndroid[1], mAssets, "images/boot_robot.png"); initTexture(&mAndroid[2], mAssets, "images/boot_robot_glow.png"); @@ -219,9 +207,9 @@ bool BootAnimation::android() glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); const int steps = 8; - for (int i=1 ; i<steps ; i++) { + for (int i = 1; i < steps; i++) { float fade = i / float(steps); - glColor4f(1, 1, 1, fade*fade); + glColor4f(1, 1, 1, fade * fade); glClear(GL_COLOR_BUFFER_BIT); glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h); eglSwapBuffers(mDisplay, mSurface); @@ -232,79 +220,73 @@ bool BootAnimation::android() glDisable(GL_BLEND); glDrawTexiOES(0, 0, 0, mAndroid[0].w, mAndroid[0].h); eglSwapBuffers(mDisplay, mSurface); - - + // update rect for the robot const int x = mWidth - mAndroid[1].w - 33; - const int y = (mHeight - mAndroid[1].h)/2 - 1; - const Rect updateRect(x, y, x+mAndroid[1].w, y+mAndroid[1].h); + const int y = (mHeight - mAndroid[1].h) / 2 - 1; + const Rect updateRect(x, y, x + mAndroid[1].w, y + mAndroid[1].h); // draw and update only what we need - eglSwapRectangleANDROID(mDisplay, mSurface, - updateRect.left, updateRect.top, - updateRect.width(), updateRect.height()); + mNativeWindowSurface->setSwapRectangle(updateRect.left, + updateRect.top, updateRect.width(), updateRect.height()); glEnable(GL_SCISSOR_TEST); - glScissor(updateRect.left, mHeight-updateRect.bottom, - updateRect.width(), updateRect.height()); + glScissor(updateRect.left, mHeight - updateRect.bottom, updateRect.width(), + updateRect.height()); const nsecs_t startTime = systemTime(); - do - { + do { // glow speed and shape nsecs_t time = systemTime() - startTime; - float t = ((4.0f/(360.0f*us2ns(16667))) * time); + float t = ((4.0f / (360.0f * us2ns(16667))) * time); t = t - floorf(t); - const float fade = 0.5f + 0.5f*sinf(t * 2*M_PI); + const float fade = 0.5f + 0.5f * sinf(t * 2 * M_PI); // fade the glow in and out glDisable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[2].name); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glColor4f(fade, fade, fade, fade); - glDrawTexiOES(updateRect.left, mHeight-updateRect.bottom, 0, + glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0, updateRect.width(), updateRect.height()); // draw the robot glEnable(GL_BLEND); glBindTexture(GL_TEXTURE_2D, mAndroid[1].name); glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glDrawTexiOES(updateRect.left, mHeight-updateRect.bottom, 0, + glDrawTexiOES(updateRect.left, mHeight - updateRect.bottom, 0, updateRect.width(), updateRect.height()); // make sure sleep a lot to not take too much CPU away from // the boot process. With this "glow" animation there is no // visible difference. - usleep(16667*4); + usleep(16667 * 4); eglSwapBuffers(mDisplay, mSurface); } while (!exitPending()); - - + glDeleteTextures(1, &mAndroid[0].name); glDeleteTextures(1, &mAndroid[1].name); glDeleteTextures(1, &mAndroid[2].name); return false; } - -bool BootAnimation::cylon() -{ +bool BootAnimation::cylon() { // initialize the textures... - initTexture(&mLeftTrail, mAssets, "images/cylon_left.png"); + initTexture(&mLeftTrail, mAssets, "images/cylon_left.png"); initTexture(&mRightTrail, mAssets, "images/cylon_right.png"); initTexture(&mBrightSpot, mAssets, "images/cylon_dot.png"); int w = mWidth; int h = mHeight; - const Point c(w/2 , h/2); + const Point c(w / 2, h / 2); const GLint amplitude = 60; - const int scx = c.x - amplitude - mBrightSpot.w/2; - const int scy = c.y - mBrightSpot.h/2; - const int scw = amplitude*2 + mBrightSpot.w; + const int scx = c.x - amplitude - mBrightSpot.w / 2; + const int scy = c.y - mBrightSpot.h / 2; + const int scw = amplitude * 2 + mBrightSpot.w; const int sch = mBrightSpot.h; - const Rect updateRect(scx, h-scy-sch, scx+scw, h-scy); + const Rect updateRect(scx, h - scy - sch, scx + scw, h - scy); // erase screen glDisable(GL_SCISSOR_TEST); @@ -314,33 +296,29 @@ bool BootAnimation::cylon() glClear(GL_COLOR_BUFFER_BIT); - eglSwapRectangleANDROID(mDisplay, mSurface, - updateRect.left, updateRect.top, - updateRect.width(), updateRect.height()); + mNativeWindowSurface->setSwapRectangle(updateRect.left, + updateRect.top, updateRect.width(), updateRect.height()); glEnable(GL_SCISSOR_TEST); glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - // clear the screen to white Point p; float t = 0; float alpha = 1.0f; const nsecs_t startTime = systemTime(); nsecs_t fadeTime = 0; - - do - { + + do { // Set scissor in interesting area - glScissor(scx, scy, scw, sch); + glScissor(scx, scy, scw, sch); // erase screen glClear(GL_COLOR_BUFFER_BIT); - // compute wave - const float a = (t * 2*M_PI) - M_PI/2; + const float a = (t * 2 * M_PI) - M_PI / 2; const float sn = sinf(a); const float cs = cosf(a); GLint x = GLint(amplitude * sn); @@ -350,50 +328,50 @@ bool BootAnimation::cylon() if (derivative > 0) { // vanishing trail... - p.x = (-amplitude + c.x) - mBrightSpot.w/2; - p.y = c.y-mLeftTrail.h/2; - float fade = 2.0f*(0.5f-t); + p.x = (-amplitude + c.x) - mBrightSpot.w / 2; + p.y = c.y - mLeftTrail.h / 2; + float fade = 2.0f * (0.5f - t); //fade *= fade; glColor4f(fade, fade, fade, fade); glBindTexture(GL_TEXTURE_2D, mLeftTrail.name); glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h); // trail... - p.x = (x + c.x) - (mRightTrail.w + mBrightSpot.w/2) + 16; - p.y = c.y-mRightTrail.h/2; - fade = t<0.25f ? t*4.0f : 1.0f; + p.x = (x + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16; + p.y = c.y - mRightTrail.h / 2; + fade = t < 0.25f ? t * 4.0f : 1.0f; fade *= fade; glColor4f(fade, fade, fade, fade); glBindTexture(GL_TEXTURE_2D, mRightTrail.name); glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h); - } else { + } else { // vanishing trail.. - p.x = (amplitude + c.x) - (mRightTrail.w + mBrightSpot.w/2) + 16; - p.y = c.y-mRightTrail.h/2; - float fade = 2.0f*(0.5f-(t-0.5f)); + p.x = (amplitude + c.x) - (mRightTrail.w + mBrightSpot.w / 2) + 16; + p.y = c.y - mRightTrail.h / 2; + float fade = 2.0f * (0.5f - (t - 0.5f)); //fade *= fade; glColor4f(fade, fade, fade, fade); glBindTexture(GL_TEXTURE_2D, mRightTrail.name); glDrawTexiOES(p.x, p.y, 0, mRightTrail.w, mRightTrail.h); // trail... - p.x = (x + c.x) - mBrightSpot.w/2; - p.y = c.y-mLeftTrail.h/2; - fade = t<0.5f+0.25f ? (t-0.5f)*4.0f : 1.0f; + p.x = (x + c.x) - mBrightSpot.w / 2; + p.y = c.y - mLeftTrail.h / 2; + fade = t < 0.5f + 0.25f ? (t - 0.5f) * 4.0f : 1.0f; fade *= fade; glColor4f(fade, fade, fade, fade); glBindTexture(GL_TEXTURE_2D, mLeftTrail.name); glDrawTexiOES(p.x, p.y, 0, mLeftTrail.w, mLeftTrail.h); } - const Point p( x + c.x-mBrightSpot.w/2, c.y-mBrightSpot.h/2 ); + const Point p(x + c.x - mBrightSpot.w / 2, c.y - mBrightSpot.h / 2); glBindTexture(GL_TEXTURE_2D, mBrightSpot.name); - glColor4f(1,0.5,0.5,1); + glColor4f(1, 0.5, 0.5, 1); glDrawTexiOES(p.x, p.y, 0, mBrightSpot.w, mBrightSpot.h); // update animation nsecs_t time = systemTime() - startTime; - t = ((4.0f/(360.0f*us2ns(16667))) * time); + t = ((4.0f / (360.0f * us2ns(16667))) * time); t = t - floorf(t); eglSwapBuffers(mDisplay, mSurface); @@ -406,7 +384,7 @@ bool BootAnimation::cylon() alpha = 1.0f - ((float(time) * 6.0f) / float(s2ns(1))); session()->openTransaction(); - mFlingerSurface->setAlpha(alpha*alpha); + mFlingerSurface->setAlpha(alpha * alpha); session()->closeTransaction(); } } while (alpha > 0); @@ -421,4 +399,5 @@ bool BootAnimation::cylon() // --------------------------------------------------------------------------- -}; // namespace android +} +; // namespace android diff --git a/libs/surfaceflinger/BootAnimation.h b/libs/surfaceflinger/BootAnimation.h index a4a6d49ded..b20cea09a4 100644 --- a/libs/surfaceflinger/BootAnimation.h +++ b/libs/surfaceflinger/BootAnimation.h @@ -26,7 +26,8 @@ #include <ui/ISurfaceComposer.h> #include <ui/SurfaceComposerClient.h> -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <GLES/gl.h> #include "Barrier.h" @@ -35,6 +36,7 @@ class SkBitmap; namespace android { class AssetManager; +class EGLNativeWindowSurface; // --------------------------------------------------------------------------- @@ -74,6 +76,7 @@ private: EGLDisplay mContext; EGLDisplay mSurface; sp<Surface> mFlingerSurface; + sp<EGLNativeWindowSurface> mNativeWindowSurface; Barrier mBarrier; }; diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp index 92588fa0d1..f14d7e99c2 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -21,14 +21,16 @@ #include <string.h> #include <math.h> -#include <GLES/egl.h> - #include <cutils/properties.h> #include <utils/Log.h> #include <ui/EGLDisplaySurface.h> +#include <GLES/gl.h> +#include <EGL/eglext.h> + + #include "DisplayHardware/DisplayHardware.h" #include <hardware/copybit.h> @@ -136,26 +138,19 @@ void DisplayHardware::init(uint32_t dpy) const char* const egl_extensions = eglQueryString( display, EGL_EXTENSIONS); - const char* egl_extensions_config = egl_extensions; - - if (strstr(egl_extensions, "EGL_ANDROID_query_string_config")) { - egl_extensions_config = eglQueryStringConfigANDROID( - display, config, EGL_EXTENSIONS); - } - LOGI("EGL informations:"); LOGI("# of configs : %d", numConfigs); LOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); LOGI("version : %s", eglQueryString(display, EGL_VERSION)); LOGI("extensions: %s", egl_extensions); - LOGI("ext/config: %s", egl_extensions_config); LOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported"); - if (strstr(egl_extensions_config, "EGL_ANDROID_swap_rectangle")) { - mFlags |= SWAP_RECTANGLE_EXTENSION; - // TODO: get the real "update_on_demand" behavior - mFlags |= UPDATE_ON_DEMAND; - } + // TODO: get this from the devfb driver (probably should be HAL module) + mFlags |= SWAP_RECTANGLE_EXTENSION; + + // TODO: get the real "update_on_demand" behavior (probably should be HAL module) + mFlags |= UPDATE_ON_DEMAND; + if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { if (dummy == EGL_SLOW_CONFIG) mFlags |= SLOW_CONFIG; @@ -173,9 +168,6 @@ void DisplayHardware::init(uint32_t dpy) if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) { if (dummy == EGL_BUFFER_PRESERVED) { mFlags |= BUFFER_PRESERVED; - if (strstr(egl_extensions_config, "EGL_ANDROID_copy_front_to_back")) { - mFlags |= COPY_BACK_EXTENSION; - } } } @@ -330,8 +322,7 @@ void DisplayHardware::flip(const Region& dirty) const if (mFlags & SWAP_RECTANGLE_EXTENSION) { const Rect& b(newDirty.bounds()); - eglSwapRectangleANDROID( - dpy, surface, + mDisplaySurface->setSwapRectangle( b.left, b.top, b.width(), b.height()); } @@ -352,3 +343,11 @@ void DisplayHardware::makeCurrent() const { eglMakeCurrent(mDisplay, mSurface, mSurface, mContext); } + +void DisplayHardware::copyFrontToImage(const copybit_image_t& front) const { + mDisplaySurface->copyFrontToImage(front); +} + +void DisplayHardware::copyBackToImage(const copybit_image_t& front) const { + mDisplaySurface->copyBackToImage(front); +} diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h index df97b60d98..550a4d1270 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -22,7 +22,7 @@ #include <ui/PixelFormat.h> #include <ui/Region.h> -#include <GLES/egl.h> +#include <EGL/egl.h> #include "DisplayHardware/DisplayHardwareBase.h" @@ -39,7 +39,6 @@ class DisplayHardware : public DisplayHardwareBase { public: enum { - COPY_BACK_EXTENSION = 0x00000001, DIRECT_TEXTURE = 0x00000002, SWAP_RECTANGLE_EXTENSION= 0x00000004, COPY_BITS_EXTENSION = 0x00000008, @@ -80,6 +79,9 @@ public: copybit_device_t* getBlitEngine() const { return mBlitEngine; } overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; } + void copyFrontToImage(const copybit_image_t& front) const; + void copyBackToImage(const copybit_image_t& front) const; + Rect bounds() const { return Rect(mWidth, mHeight); } diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp index bdefba34e2..0cf53f796b 100644 --- a/libs/surfaceflinger/LayerBase.cpp +++ b/libs/surfaceflinger/LayerBase.cpp @@ -23,6 +23,11 @@ #include <utils/Errors.h> #include <utils/Log.h> +#include <GLES/gl.h> +#include <GLES/glext.h> + +#include <hardware/hardware.h> + #include "clz.h" #include "LayerBase.h" #include "LayerBlur.h" @@ -111,6 +116,12 @@ void LayerBase::commitTransaction(bool skipSize) { mDrawingState.h = h; } } +void LayerBase::forceVisibilityTransaction() { + // this can be called without SurfaceFlinger.mStateLock, but if we + // can atomically increment the sequence number, it doesn't matter. + android_atomic_inc(&mCurrentState.sequence); + requestTransaction(); +} bool LayerBase::requestTransaction() { int32_t old = setTransactionFlags(eTransactionNeeded); return ((old & eTransactionNeeded) == 0); @@ -350,6 +361,10 @@ void LayerBase::draw(const Region& inClip) const return; } } + + // reset GL state + glEnable(GL_SCISSOR_TEST); + onDraw(clip); /* @@ -391,6 +406,7 @@ void LayerBase::clearWithOpenGL(const Region& clip) const Rect r; Region::iterator iterator(clip); if (iterator) { + glEnable(GL_SCISSOR_TEST); glVertexPointer(2, GL_FIXED, 0, mVertices); while (iterator.iterate(&r)) { const GLint sy = fbHeight - (r.top + r.height()); @@ -401,7 +417,7 @@ void LayerBase::clearWithOpenGL(const Region& clip) const } void LayerBase::drawWithOpenGL(const Region& clip, - GLint textureName, const GGLSurface& t) const + GLint textureName, const GGLSurface& t, int transform) const { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t fbHeight = hw.getHeight(); @@ -473,6 +489,12 @@ void LayerBase::drawWithOpenGL(const Region& clip, glMatrixMode(GL_TEXTURE); glLoadIdentity(); + + if (transform == HAL_TRANSFORM_ROT_90) { + glTranslatef(0, 1, 0); + glRotatef(-90, 0, 0, 1); + } + if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) { // find the smallest power-of-two that will accommodate our surface GLuint tw = 1 << (31 - clz(t.width)); diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h index 5e14dc85c7..a020f44e87 100644 --- a/libs/surfaceflinger/LayerBase.h +++ b/libs/surfaceflinger/LayerBase.h @@ -86,8 +86,8 @@ public: uint32_t z; uint8_t alpha; uint8_t flags; - uint8_t sequence; // changes when visible regions can change - uint8_t reserved; + uint8_t reserved[2]; + int32_t sequence; // changes when visible regions can change uint32_t tint; Transform transform; Region transparentRegion; @@ -104,11 +104,11 @@ public: void commitTransaction(bool skipSize); bool requestTransaction(); - + void forceVisibilityTransaction(); + uint32_t getTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags); - void validateVisibility(const Transform& globalTransform); Rect visibleBounds() const; void drawRegion(const Region& reg) const; @@ -162,7 +162,12 @@ public: * the bitmap (as opposed to the size of the drawing state). */ virtual Point getPhysicalSize() const; - + + /** + * validateVisibility - cache a bunch of things + */ + virtual void validateVisibility(const Transform& globalTransform); + /** * lockPageFlip - called each time the screen is redrawn and returns whether * the visible regions need to be recomputed (this is a fairly heavy @@ -188,10 +193,15 @@ public: * needsBlending - true if this surface needs blending */ virtual bool needsBlending() const { return false; } - + + /** + * transformed -- true is this surface needs a to be transformed + */ + virtual bool transformed() const { return mTransformed; } + /** - * isSecure - true if this surface is secure, that is if it prevents a - * screenshot to be taken, + * isSecure - true if this surface is secure, that is if it prevents + * screenshots or vns servers. */ virtual bool isSecure() const { return false; } @@ -210,7 +220,6 @@ public: } int32_t getOrientation() const { return mOrientation; } - bool transformed() const { return mTransformed; } int tx() const { return mLeft; } int ty() const { return mTop; } @@ -221,7 +230,9 @@ protected: GLuint createTexture() const; void drawWithOpenGL(const Region& clip, - GLint textureName, const GGLSurface& surface) const; + GLint textureName, + const GGLSurface& surface, + int transform = 0) const; void clearWithOpenGL(const Region& clip) const; @@ -320,8 +331,7 @@ public: *params = mParams; } - virtual status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap) + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers) { return INVALID_OPERATION; } virtual void postBuffer(ssize_t offset) { } virtual void unregisterBuffers() { }; diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp index 7c98857fc2..e84435088a 100644 --- a/libs/surfaceflinger/LayerBitmap.cpp +++ b/libs/surfaceflinger/LayerBitmap.cpp @@ -69,18 +69,15 @@ status_t LayerBitmap::setBits(uint32_t w, uint32_t h, uint32_t alignment, return NO_ERROR; } + PixelFormatInfo info; + getPixelFormatInfo(format, &info); + uint32_t allocFlags = MemoryDealer::PAGE_ALIGNED; const uint32_t align = 4; // must match GL_UNPACK_ALIGNMENT - const uint32_t Bpp = bytesPerPixel(format); + const uint32_t Bpp = info.bytesPerPixel; uint32_t stride = (w + (alignment-1)) & ~(alignment-1); stride = ((stride * Bpp + (align-1)) & ~(align-1)) / Bpp; - size_t size = stride * h * Bpp; - if (format == PIXEL_FORMAT_YCbCr_422_SP || - format == PIXEL_FORMAT_YCbCr_420_SP) { - // in YUV planar, bitsPerPixel is for the Y plane - size = (size * bitsPerPixel(format)) / 8; - } - + size_t size = info.getScanlineSize(stride) * h; if (allocFlags & MemoryDealer::PAGE_ALIGNED) { size_t pagesize = getpagesize(); size = (size + (pagesize-1)) & ~(pagesize-1); diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h index 4c2eb50df5..9ad64c40be 100644 --- a/libs/surfaceflinger/LayerBitmap.h +++ b/libs/surfaceflinger/LayerBitmap.h @@ -70,9 +70,6 @@ public: void getBitmapSurface(copybit_image_t* img) const; private: - LayerBitmap(const LayerBitmap& rhs); - LayerBitmap& operator = (const LayerBitmap& rhs); - sp<MemoryDealer> mAllocator; sp<IMemory> mBitsMemory; uint32_t mAllocFlags; diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index efadbcf4c6..d3e456f1bf 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -23,6 +23,9 @@ #include <utils/Errors.h> #include <utils/Log.h> +#include <GLES/gl.h> +#include <GLES/glext.h> + #include "BlurFilter.h" #include "LayerBlur.h" #include "SurfaceFlinger.h" diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp index c9cebf4c91..00fab70d49 100644 --- a/libs/surfaceflinger/LayerBuffer.cpp +++ b/libs/surfaceflinger/LayerBuffer.cpp @@ -25,6 +25,9 @@ #include <utils/Log.h> #include <utils/StopWatch.h> +#include <utils/IPCThreadState.h> +#include <utils/IServiceManager.h> + #include <ui/PixelFormat.h> #include <ui/EGLDisplaySurface.h> @@ -129,18 +132,24 @@ void LayerBuffer::onDraw(const Region& clip) const } } +bool LayerBuffer::transformed() const +{ + sp<Source> source(getSource()); + if (LIKELY(source != 0)) + return source->transformed(); + return false; +} + /** * This creates a "buffer" source for this surface */ -status_t LayerBuffer::registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& memoryHeap) +status_t LayerBuffer::registerBuffers(const ISurface::BufferHeap& buffers) { Mutex::Autolock _l(mLock); if (mSource != 0) return INVALID_OPERATION; - sp<BufferSource> source = new BufferSource(*this, w, h, - hstride, vstride, format, memoryHeap); + sp<BufferSource> source = new BufferSource(*this, buffers); status_t result = source->getStatus(); if (result == NO_ERROR) { @@ -194,13 +203,39 @@ LayerBuffer::SurfaceBuffer::~SurfaceBuffer() mOwner = 0; } -status_t LayerBuffer::SurfaceBuffer::registerBuffers( - int w, int h, int hs, int vs, - PixelFormat format, const sp<IMemoryHeap>& heap) +status_t LayerBuffer::SurfaceBuffer::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) +{ + switch (code) { + case REGISTER_BUFFERS: + case UNREGISTER_BUFFERS: + case CREATE_OVERLAY: + { + // codes that require permission check + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int self_pid = getpid(); + if (LIKELY(pid != self_pid)) { + // we're called from a different process, do the real check + if (!checkCallingPermission( + String16("android.permission.ACCESS_SURFACE_FLINGER"))) + { + const int uid = ipc->getCallingUid(); + LOGE("Permission Denial: " + "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); + return PERMISSION_DENIED; + } + } + } + } + return LayerBaseClient::Surface::onTransact(code, data, reply, flags); +} + +status_t LayerBuffer::SurfaceBuffer::registerBuffers(const ISurface::BufferHeap& buffers) { LayerBuffer* owner(getOwner()); if (owner) - return owner->registerBuffers(w, h, hs, vs, format, heap); + return owner->registerBuffers(buffers); return NO_INIT; } @@ -237,23 +272,20 @@ void LayerBuffer::SurfaceBuffer::disown() // LayerBuffer::Buffer // ============================================================================ -LayerBuffer::Buffer::Buffer(const sp<IMemoryHeap>& heap, ssize_t offset, - int w, int h, int hs, int vs, int f) -: mHeap(heap) +LayerBuffer::Buffer::Buffer(const ISurface::BufferHeap& buffers, ssize_t offset) + : mBufferHeap(buffers) { NativeBuffer& src(mNativeBuffer); src.crop.l = 0; src.crop.t = 0; - src.crop.r = w; - src.crop.b = h; - src.img.w = hs ?: w; - src.img.h = vs ?: h; - src.img.format = f; + src.crop.r = buffers.w; + src.crop.b = buffers.h; + src.img.w = buffers.hor_stride ?: buffers.w; + src.img.h = buffers.ver_stride ?: buffers.h; + src.img.format = buffers.format; src.img.offset = offset; - src.img.base = heap->base(); - src.img.fd = heap->heapID(); - // FIXME: make sure this buffer lies within the heap, in which case, set - // mHeap to null + src.img.base = buffers.heap->base(); + src.img.fd = buffers.heap->heapID(); } LayerBuffer::Buffer::~Buffer() @@ -283,41 +315,55 @@ void LayerBuffer::Source::postBuffer(ssize_t offset) { } void LayerBuffer::Source::unregisterBuffers() { } +bool LayerBuffer::Source::transformed() const { + return mLayer.mTransformed; +} // --------------------------------------------------------------------------- LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer, - int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& memoryHeap) - : Source(layer), mStatus(NO_ERROR), mTextureName(-1U) + const ISurface::BufferHeap& buffers) + : Source(layer), mStatus(NO_ERROR), + mBufferSize(0), mTextureName(-1U) { - if (memoryHeap == NULL) { + if (buffers.heap == NULL) { // this is allowed, but in this case, it is illegal to receive // postBuffer(). The surface just erases the framebuffer with // fully transparent pixels. - mHeap.clear(); - mWidth = w; - mHeight = h; + mBufferHeap = buffers; mLayer.setNeedsBlending(false); return; } - status_t err = (memoryHeap->heapID() >= 0) ? NO_ERROR : NO_INIT; + status_t err = (buffers.heap->heapID() >= 0) ? NO_ERROR : NO_INIT; if (err != NO_ERROR) { + LOGE("LayerBuffer::BufferSource: invalid heap (%s)", strerror(err)); mStatus = err; return; } - - // TODO: validate format/parameters - mHeap = memoryHeap; - mWidth = w; - mHeight = h; - mHStride = hstride; - mVStride = vstride; - mFormat = format; + PixelFormatInfo info; - getPixelFormatInfo(format, &info); - mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0); + err = getPixelFormatInfo(buffers.format, &info); + if (err != NO_ERROR) { + LOGE("LayerBuffer::BufferSource: invalid format %d (%s)", + buffers.format, strerror(err)); + mStatus = err; + return; + } + + if (buffers.hor_stride<0 || buffers.ver_stride<0) { + LOGE("LayerBuffer::BufferSource: invalid parameters " + "(w=%d, h=%d, xs=%d, ys=%d)", + buffers.w, buffers.h, buffers.hor_stride, buffers.ver_stride); + mStatus = BAD_VALUE; + return; + } + + mBufferHeap = buffers; + mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0); + mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride; + mLayer.forceVisibilityTransaction(); + } LayerBuffer::BufferSource::~BufferSource() @@ -329,21 +375,24 @@ LayerBuffer::BufferSource::~BufferSource() void LayerBuffer::BufferSource::postBuffer(ssize_t offset) { - sp<IMemoryHeap> heap; - int w, h, hs, vs, f; + ISurface::BufferHeap buffers; { // scope for the lock Mutex::Autolock _l(mLock); - w = mWidth; - h = mHeight; - hs= mHStride; - vs= mVStride; - f = mFormat; - heap = mHeap; + buffers = mBufferHeap; + if (buffers.heap != 0) { + const size_t memorySize = buffers.heap->getSize(); + if ((size_t(offset) + mBufferSize) > memorySize) { + LOGE("LayerBuffer::BufferSource::postBuffer() " + "invalid buffer (offset=%d, size=%d, heap-size=%d", + int(offset), int(mBufferSize), int(memorySize)); + return; + } + } } sp<Buffer> buffer; - if (heap != 0) { - buffer = new LayerBuffer::Buffer(heap, offset, w, h, hs, vs, f); + if (buffers.heap != 0) { + buffer = new LayerBuffer::Buffer(buffers, offset); if (buffer->getStatus() != NO_ERROR) buffer.clear(); setBuffer(buffer); @@ -354,7 +403,7 @@ void LayerBuffer::BufferSource::postBuffer(ssize_t offset) void LayerBuffer::BufferSource::unregisterBuffers() { Mutex::Autolock _l(mLock); - mHeap.clear(); + mBufferHeap.heap.clear(); mBuffer.clear(); mLayer.invalidate(); } @@ -371,6 +420,11 @@ void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer) mBuffer = buffer; } +bool LayerBuffer::BufferSource::transformed() const +{ + return mBufferHeap.transform ? true : Source::transformed(); +} + void LayerBuffer::BufferSource::onDraw(const Region& clip) const { sp<Buffer> buffer(getBuffer()); @@ -417,7 +471,7 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const if (UNLIKELY(mTemporaryDealer == 0)) { // allocate a memory-dealer for this the first time mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager() - ->createHeap(ISurfaceComposer::eHardware); + ->createHeap(ISurfaceComposer::eHardware); mTempBitmap.init(mTemporaryDealer); } @@ -447,16 +501,31 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const copybit_image_t dst; hw.getDisplaySurface(&dst); const copybit_rect_t& drect - = reinterpret_cast<const copybit_rect_t&>(transformedBounds); + = reinterpret_cast<const copybit_rect_t&>(transformedBounds); const State& s(mLayer.drawingState()); region_iterator it(clip); - copybit->set_parameter(copybit, COPYBIT_TRANSFORM, mLayer.getOrientation()); + + // pick the right orientation for this buffer + int orientation = mLayer.getOrientation(); + if (UNLIKELY(mBufferHeap.transform)) { + Transform rot90; + GraphicPlane::orientationToTransfrom( + ISurfaceComposer::eOrientation90, 0, 0, &rot90); + const Transform& planeTransform(mLayer.graphicPlane(0).transform()); + const Layer::State& s(mLayer.drawingState()); + Transform tr(planeTransform * s.transform * rot90); + orientation = tr.getOrientation(); + } + + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation); copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha); - copybit->set_parameter(copybit, COPYBIT_DITHER, - s.flags & ISurfaceComposer::eLayerDither ? - COPYBIT_ENABLE : COPYBIT_DISABLE); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); + err = copybit->stretch(copybit, &dst, &src.img, &drect, &src.crop, &it); + if (err != NO_ERROR) { + LOGE("copybit failed (%s)", strerror(err)); + } } if (!can_use_copybit || err) { @@ -475,10 +544,11 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset); const Region dirty(Rect(t.width, t.height)); mLayer.loadTexture(dirty, mTextureName, t, w, h); - mLayer.drawWithOpenGL(clip, mTextureName, t); + mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform); } } + // --------------------------------------------------------------------------- LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer, diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 6e3d49f053..2dc77f1501 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -22,7 +22,7 @@ #include <utils/IMemory.h> #include <private/ui/LayerState.h> -#include <GLES/eglnatives.h> +#include <EGL/eglnatives.h> #include "LayerBase.h" #include "LayerBitmap.h" @@ -46,6 +46,7 @@ class LayerBuffer : public LayerBaseClient virtual void onVisibilityResolved(const Transform& planeTransform); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); + virtual bool transformed() const; protected: LayerBuffer& mLayer; }; @@ -67,9 +68,9 @@ public: virtual void onDraw(const Region& clip) const; virtual uint32_t doTransaction(uint32_t flags); virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion); + virtual bool transformed() const; - status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap); + status_t registerBuffers(const ISurface::BufferHeap& buffers); void postBuffer(ssize_t offset); void unregisterBuffers(); sp<OverlayRef> createOverlay(uint32_t w, uint32_t h, int32_t format); @@ -89,10 +90,9 @@ private: class Buffer : public LightRefBase<Buffer> { public: - Buffer(const sp<IMemoryHeap>& heap, ssize_t offset, - int w, int h, int hs, int vs, int f); + Buffer(const ISurface::BufferHeap& buffers, ssize_t offset); inline status_t getStatus() const { - return mHeap!=0 ? NO_ERROR : NO_INIT; + return mBufferHeap.heap!=0 ? NO_ERROR : NO_INIT; } inline const NativeBuffer& getBuffer() const { return mNativeBuffer; @@ -103,15 +103,13 @@ private: Buffer(const Buffer& rhs); ~Buffer(); private: - sp<IMemoryHeap> mHeap; - NativeBuffer mNativeBuffer; + ISurface::BufferHeap mBufferHeap; + NativeBuffer mNativeBuffer; }; class BufferSource : public Source { public: - BufferSource(LayerBuffer& layer, - int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap); + BufferSource(LayerBuffer& layer, const ISurface::BufferHeap& buffers); virtual ~BufferSource(); status_t getStatus() const { return mStatus; } @@ -121,16 +119,13 @@ private: virtual void onDraw(const Region& clip) const; virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); + virtual bool transformed() const; private: mutable Mutex mLock; - sp<IMemoryHeap> mHeap; sp<Buffer> mBuffer; status_t mStatus; - int mWidth; - int mHeight; - int mHStride; - int mVStride; - int mFormat; + ISurface::BufferHeap mBufferHeap; + size_t mBufferSize; mutable sp<MemoryDealer> mTemporaryDealer; mutable LayerBitmap mTempBitmap; mutable GLuint mTextureName; @@ -186,8 +181,9 @@ private: public: SurfaceBuffer(SurfaceID id, LayerBuffer* owner); virtual ~SurfaceBuffer(); - virtual status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap); + virtual status_t onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); + virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); virtual void postBuffer(ssize_t offset); virtual void unregisterBuffers(); virtual sp<OverlayRef> createOverlay( diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp new file mode 100644 index 0000000000..2b72d7ce94 --- /dev/null +++ b/libs/surfaceflinger/LayerOrientationAnim.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SurfaceFlinger" + +#include <stdlib.h> +#include <stdint.h> +#include <sys/types.h> + +#include <utils/Errors.h> +#include <utils/Log.h> + +#include <core/SkBitmap.h> + +#include <ui/EGLDisplaySurface.h> + +#include "LayerBase.h" +#include "LayerOrientationAnim.h" +#include "SurfaceFlinger.h" +#include "DisplayHardware/DisplayHardware.h" +#include "OrientationAnimation.h" + +namespace android { +// --------------------------------------------------------------------------- + +const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80; +const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim"; + +// --------------------------------------------------------------------------- + +LayerOrientationAnim::LayerOrientationAnim( + SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const LayerBitmap& bitmap, + const LayerBitmap& bitmapIn) + : LayerBase(flinger, display), mAnim(anim), + mBitmap(bitmap), mBitmapIn(bitmapIn), + mTextureName(-1), mTextureNameIn(-1) +{ + mStartTime = systemTime(); + mFinishTime = 0; + mOrientationCompleted = false; + mFirstRedraw = false; + mLastNormalizedTime = 0; + mLastScale = 0; + mNeedsBlending = false; +} + +LayerOrientationAnim::~LayerOrientationAnim() +{ + if (mTextureName != -1U) { + LayerBase::deletedTextures.add(mTextureName); + } + if (mTextureNameIn != -1U) { + LayerBase::deletedTextures.add(mTextureNameIn); + } +} + +bool LayerOrientationAnim::needsBlending() const +{ + return mNeedsBlending; +} + +Point LayerOrientationAnim::getPhysicalSize() const +{ + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + return Point(hw.getWidth(), hw.getHeight()); +} + +void LayerOrientationAnim::validateVisibility(const Transform&) +{ + const Layer::State& s(drawingState()); + const Transform tr(s.transform); + const Point size(getPhysicalSize()); + uint32_t w = size.x; + uint32_t h = size.y; + mTransformedBounds = tr.makeBounds(w, h); + mLeft = tr.tx(); + mTop = tr.ty(); + transparentRegionScreen.clear(); + mTransformed = true; + mCanUseCopyBit = false; + copybit_device_t* copybit = mFlinger->getBlitEngine(); + if (copybit) { + mCanUseCopyBit = true; + } +} + +void LayerOrientationAnim::onOrientationCompleted() +{ + mFinishTime = systemTime(); + mOrientationCompleted = true; + mFirstRedraw = true; + mNeedsBlending = true; + mFlinger->invalidateLayerVisibility(this); +} + +void LayerOrientationAnim::onDraw(const Region& clip) const +{ + // Animation... + const float MIN_SCALE = 0.5f; + const float DURATION = ms2ns(200); + const float BOUNCES_PER_SECOND = 1.618f; + const float BOUNCES_AMPLITUDE = 1.0f/32.0f; + + const nsecs_t now = systemTime(); + float scale, alpha; + + if (mOrientationCompleted) { + if (mFirstRedraw) { + mFirstRedraw = false; + + // make a copy of what's on screen + copybit_image_t image; + mBitmapIn.getBitmapSurface(&image); + const DisplayHardware& hw(graphicPlane(0).displayHardware()); + hw.copyBackToImage(image); + + // and erase the screen for this round + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + + // FIXME: code below is gross + mNeedsBlending = false; + LayerOrientationAnim* self(const_cast<LayerOrientationAnim*>(this)); + mFlinger->invalidateLayerVisibility(self); + } + + // make sure pick-up where we left off + const float duration = DURATION * mLastNormalizedTime; + const float normalizedTime = (float(now - mFinishTime) / duration); + if (normalizedTime <= 1.0f) { + const float squaredTime = normalizedTime*normalizedTime; + scale = (1.0f - mLastScale)*squaredTime + mLastScale; + alpha = (1.0f - normalizedTime); + alpha *= alpha; + alpha *= alpha; + } else { + mAnim->onAnimationFinished(); + scale = 1.0f; + alpha = 0.0f; + } + } else { + const float normalizedTime = float(now - mStartTime) / DURATION; + if (normalizedTime <= 1.0f) { + mLastNormalizedTime = normalizedTime; + const float squaredTime = normalizedTime*normalizedTime; + scale = (MIN_SCALE-1.0f)*squaredTime + 1.0f; + alpha = 1.0f; + } else { + mLastNormalizedTime = 1.0f; + const float to_seconds = DURATION / seconds(1); + const float phi = BOUNCES_PER_SECOND * + (((normalizedTime - 1.0f) * to_seconds)*M_PI*2); + scale = MIN_SCALE + BOUNCES_AMPLITUDE * (1.0f - cosf(phi)); + alpha = 1.0f; + } + mLastScale = scale; + } + drawScaled(scale, alpha); +} + +void LayerOrientationAnim::drawScaled(float f, float alpha) const +{ + copybit_image_t dst; + const GraphicPlane& plane(graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + hw.getDisplaySurface(&dst); + + // clear screen + // TODO: with update on demand, we may be able + // to not erase the screen at all during the animation + if (!mOrientationCompleted) { + glDisable(GL_BLEND); + glDisable(GL_DITHER); + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT); + } + + const int w = dst.w*f; + const int h = dst.h*f; + const int xc = uint32_t(dst.w-w)/2; + const int yc = uint32_t(dst.h-h)/2; + const copybit_rect_t drect = { xc, yc, xc+w, yc+h }; + + copybit_image_t src; + mBitmap.getBitmapSurface(&src); + const copybit_rect_t srect = { 0, 0, src.w, src.h }; + + int err = NO_ERROR; + const int can_use_copybit = canUseCopybit(); + if (can_use_copybit) { + copybit_device_t* copybit = mFlinger->getBlitEngine(); + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0); + copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE); + + if (alpha < 1.0f) { + copybit_image_t srcIn; + mBitmapIn.getBitmapSurface(&srcIn); + region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b ))); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF); + err = copybit->stretch(copybit, &dst, &srcIn, &drect, &srect, &it); + } + + if (!err && alpha > 0.0f) { + region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b ))); + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alpha*255)); + err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it); + } + LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err)); + } + if (!can_use_copybit || err) { + GGLSurface t; + t.version = sizeof(GGLSurface); + t.width = src.w; + t.height = src.h; + t.stride = src.w; + t.vstride= src.h; + t.format = src.format; + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + + Transform tr; + tr.set(f,0,0,f); + tr.set(xc, yc); + + // FIXME: we should not access mVertices and mDrawingState like that, + // but since we control the animation, we know it's going to work okay. + // eventually we'd need a more formal way of doing things like this. + LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this)); + tr.transform(self.mVertices[0], 0, 0); + tr.transform(self.mVertices[1], 0, src.h); + tr.transform(self.mVertices[2], src.w, src.h); + tr.transform(self.mVertices[3], src.w, 0); + if (!(mFlags & DisplayHardware::SLOW_CONFIG)) { + // Too slow to do this in software + self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter; + } + + if (alpha < 1.0f) { + copybit_image_t src; + mBitmapIn.getBitmapSurface(&src); + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureNameIn == -1LU)) { + mTextureNameIn = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureNameIn, t, w, h); + } + self.mDrawingState.alpha = 255; + const Region clip(Rect( drect.l, drect.t, drect.r, drect.b )); + drawWithOpenGL(clip, mTextureName, t); + } + + t.data = (GGLubyte*)(intptr_t(src.base) + src.offset); + if (UNLIKELY(mTextureName == -1LU)) { + mTextureName = createTexture(); + GLuint w=0, h=0; + const Region dirty(Rect(t.width, t.height)); + loadTexture(dirty, mTextureName, t, w, h); + } + self.mDrawingState.alpha = int(alpha*255); + const Region clip(Rect( drect.l, drect.t, drect.r, drect.b )); + drawWithOpenGL(clip, mTextureName, t); + } +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/LayerScreenshot.h b/libs/surfaceflinger/LayerOrientationAnim.h index 2d9a8ec6d7..73676859bc 100644 --- a/libs/surfaceflinger/LayerScreenshot.h +++ b/libs/surfaceflinger/LayerOrientationAnim.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ANDROID_LAYER_SCREENSHOT_H -#define ANDROID_LAYER_SCREENSHOT_H +#ifndef ANDROID_LAYER_ORIENTATION_ANIM_H +#define ANDROID_LAYER_ORIENTATION_ANIM_H #include <stdint.h> #include <sys/types.h> @@ -23,12 +23,14 @@ #include <utils/Parcel.h> #include "LayerBase.h" +#include "LayerBitmap.h" namespace android { // --------------------------------------------------------------------------- +class OrientationAnimation; -class LayerScreenshot : public LayerBase +class LayerOrientationAnim : public LayerBase { public: static const uint32_t typeInfo; @@ -36,22 +38,38 @@ public: virtual char const* getTypeID() const { return typeID; } virtual uint32_t getTypeInfo() const { return typeInfo; } - LayerScreenshot(SurfaceFlinger* flinger, DisplayID display); - virtual ~LayerScreenshot(); + LayerOrientationAnim(SurfaceFlinger* flinger, DisplayID display, + OrientationAnimation* anim, + const LayerBitmap& zoomOut, + const LayerBitmap& zoomIn); + virtual ~LayerOrientationAnim(); + + void onOrientationCompleted(); virtual void onDraw(const Region& clip) const; - virtual bool needsBlending() const { return true; } + virtual Point getPhysicalSize() const; + virtual void validateVisibility(const Transform& globalTransform); + virtual bool needsBlending() const; virtual bool isSecure() const { return false; } - - void takeScreenshot(Mutex& lock, Parcel* reply); - private: - mutable Condition mCV; - Parcel* mReply; + void drawScaled(float scale, float alpha) const; + + OrientationAnimation* mAnim; + LayerBitmap mBitmap; + LayerBitmap mBitmapIn; + nsecs_t mStartTime; + nsecs_t mFinishTime; + bool mOrientationCompleted; + mutable bool mFirstRedraw; + mutable float mLastNormalizedTime; + mutable float mLastScale; + mutable GLuint mTextureName; + mutable GLuint mTextureNameIn; + mutable bool mNeedsBlending; }; // --------------------------------------------------------------------------- }; // namespace android -#endif // ANDROID_LAYER_SCREENSHOT_H +#endif // ANDROID_LAYER_ORIENTATION_ANIM_H diff --git a/libs/surfaceflinger/OrientationAnimation.cpp b/libs/surfaceflinger/OrientationAnimation.cpp new file mode 100644 index 0000000000..f6f1326b10 --- /dev/null +++ b/libs/surfaceflinger/OrientationAnimation.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "SurfaceFlinger" + +#include <stdint.h> +#include <sys/types.h> +#include <limits.h> + +#include "LayerOrientationAnim.h" +#include "OrientationAnimation.h" +#include "SurfaceFlinger.h" +#include "VRamHeap.h" + +#include "DisplayHardware/DisplayHardware.h" + +namespace android { + +// --------------------------------------------------------------------------- + +OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger) + : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE) +{ + // allocate a memory-dealer for this the first time + mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap( + ISurfaceComposer::eHardware); +} + +OrientationAnimation::~OrientationAnimation() +{ +} + +void OrientationAnimation::onOrientationChanged() +{ + if (mState == DONE) + mState = PREPARE; +} + +void OrientationAnimation::onAnimationFinished() +{ + if (mState != DONE) + mState = FINISH; +} + +bool OrientationAnimation::run_impl() +{ + bool skip_frame; + switch (mState) { + default: + case DONE: + skip_frame = done(); + break; + case PREPARE: + skip_frame = prepare(); + break; + case PHASE1: + skip_frame = phase1(); + break; + case PHASE2: + skip_frame = phase2(); + break; + case FINISH: + skip_frame = finished(); + break; + } + return skip_frame; +} + +bool OrientationAnimation::done() +{ + if (mFlinger->isFrozen()) { + // we are not allowed to draw, but pause a bit to make sure + // apps don't end up using the whole CPU, if they depend on + // surfaceflinger for synchronization. + usleep(8333); // 8.3ms ~ 120fps + return true; + } + return false; +} + +bool OrientationAnimation::prepare() +{ + mState = PHASE1; + + const GraphicPlane& plane(mFlinger->graphicPlane(0)); + const DisplayHardware& hw(plane.displayHardware()); + const uint32_t w = hw.getWidth(); + const uint32_t h = hw.getHeight(); + + LayerBitmap bitmap; + bitmap.init(mTemporaryDealer); + bitmap.setBits(w, h, 1, hw.getFormat()); + + LayerBitmap bitmapIn; + bitmapIn.init(mTemporaryDealer); + bitmapIn.setBits(w, h, 1, hw.getFormat()); + + copybit_image_t front; + bitmap.getBitmapSurface(&front); + hw.copyFrontToImage(front); + + LayerOrientationAnim* l = new LayerOrientationAnim( + mFlinger.get(), 0, this, bitmap, bitmapIn); + l->initStates(w, h, 0); + l->setLayer(INT_MAX-1); + mFlinger->addLayer(l); + mLayerOrientationAnim = l; + return true; +} + +bool OrientationAnimation::phase1() +{ + if (mFlinger->isFrozen() == false) { + // start phase 2 + mState = PHASE2; + mLayerOrientationAnim->onOrientationCompleted(); + mLayerOrientationAnim->invalidate(); + return true; + + } + mLayerOrientationAnim->invalidate(); + return false; +} + +bool OrientationAnimation::phase2() +{ + // do the 2nd phase of the animation + mLayerOrientationAnim->invalidate(); + return false; +} + +bool OrientationAnimation::finished() +{ + mState = DONE; + mFlinger->removeLayer(mLayerOrientationAnim); + mLayerOrientationAnim = NULL; + return true; +} + +// --------------------------------------------------------------------------- + +}; // namespace android diff --git a/libs/surfaceflinger/OrientationAnimation.h b/libs/surfaceflinger/OrientationAnimation.h new file mode 100644 index 0000000000..ba33fcedd4 --- /dev/null +++ b/libs/surfaceflinger/OrientationAnimation.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_ORIENTATION_ANIMATION_H +#define ANDROID_ORIENTATION_ANIMATION_H + +#include <stdint.h> +#include <sys/types.h> + +#include "SurfaceFlinger.h" + +namespace android { + +// --------------------------------------------------------------------------- + +class SurfaceFlinger; +class MemoryDealer; +class LayerOrientationAnim; + +class OrientationAnimation +{ +public: + OrientationAnimation(const sp<SurfaceFlinger>& flinger); + virtual ~OrientationAnimation(); + + void onOrientationChanged(); + void onAnimationFinished(); + inline bool run() { + if (LIKELY(mState == DONE)) + return false; + return run_impl(); + } + +private: + enum { + DONE = 0, + PREPARE, + PHASE1, + PHASE2, + FINISH + }; + + bool run_impl(); + bool done(); + bool prepare(); + bool phase1(); + bool phase2(); + bool finished(); + + sp<SurfaceFlinger> mFlinger; + sp<MemoryDealer> mTemporaryDealer; + LayerOrientationAnim* mLayerOrientationAnim; + int mState; +}; + +// --------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_ORIENTATION_ANIMATION_H diff --git a/libs/surfaceflinger/RFBServer.cpp b/libs/surfaceflinger/RFBServer.cpp deleted file mode 100644 index c2c1989413..0000000000 --- a/libs/surfaceflinger/RFBServer.cpp +++ /dev/null @@ -1,722 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "RFBServer" - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <errno.h> -#include <fcntl.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ioctl.h> - -#include <netinet/in.h> - -#include <cutils/sockets.h> - -#include <utils/Log.h> -#include <ui/Rect.h> - -#ifdef HAVE_ANDROID_OS -#include <linux/input.h> -#endif - -#include "RFBServer.h" -#include "SurfaceFlinger.h" - -/* BUG=773511: this is a temporary hack required while developing the new - set of "clean kernel headers" for the Bionic C library. */ -#ifndef KEY_STAR -#define KEY_STAR 227 -#endif -#ifndef KEY_SHARP -#define KEY_SHARP 228 -#endif -#ifndef KEY_SOFT1 -#define KEY_SOFT1 229 -#endif -#ifndef KEY_SOFT2 -#define KEY_SOFT2 230 -#endif -#ifndef KEY_CENTER -#define KEY_CENTER 232 -#endif - -// ---------------------------------------------------------------------------- - -#define DEBUG_MSG 0 - -// ---------------------------------------------------------------------------- - -namespace android { - -const int VNC_PORT = 5900; - -RFBServer::RFBServer(uint32_t w, uint32_t h, android::PixelFormat format) - : Thread(false), mFD(-1), mStatus(NO_INIT), mIoVec(0) -{ - mFrameBuffer.version = sizeof(mFrameBuffer); - mFrameBuffer.width = w; - mFrameBuffer.height = h; - mFrameBuffer.stride = w; - mFrameBuffer.format = format; - mFrameBuffer.data = 0; -} - -RFBServer::~RFBServer() -{ - if (mRobinThread != 0) { - // ask the thread to exit first - mRobinThread->exitAndWait(); - } - - free(mFrameBuffer.data); - - delete [] mIoVec; -} - -void RFBServer::onFirstRef() -{ - run("Batman"); -} - -status_t RFBServer::readyToRun() -{ - LOGI("RFB server ready to run"); - return NO_ERROR; -} - -bool RFBServer::threadLoop() -{ - struct sockaddr addr; - socklen_t alen; - int serverfd = -1; - int port = VNC_PORT; - - do { - retry: - if (serverfd < 0) { - serverfd = socket_loopback_server(port, SOCK_STREAM); - if (serverfd < 0) { - if ((errno == EADDRINUSE) && (port < (VNC_PORT+10))) { - LOGW("port %d already in use, trying %d", port, port+1); - port++; - goto retry; - } - LOGE("couldn't create socket, port=%d, error %d (%s)", - port, errno, strerror(errno)); - sleep(1); - break; - } - fcntl(serverfd, F_SETFD, FD_CLOEXEC); - } - - alen = sizeof(addr); - mFD = accept(serverfd, &addr, &alen); - - if (mFD < 0) { - LOGE("couldn't accept(), error %d (%s)", errno, strerror(errno)); - // we could have run out of file descriptors, wait a bit and - // try again. - sleep(1); - goto retry; - } - fcntl(mFD, F_SETFD, FD_CLOEXEC); - - // send protocol version and Authentication method - mStatus = NO_ERROR; - handshake(3, 3, Authentication::None); - - if (alive()) { - // create the thread we use to send data to the client - mRobinThread = new ServerThread(this); - } - - while( alive() ) { - // client message must be destroyed at each iteration - // (most of the time this is a no-op) - ClientMessage msg; - waitForClientMessage(msg); - if (alive()) { - handleClientMessage(msg); - } - } - - } while( alive() ); - - // free-up some resources - if (mRobinThread != 0) { - mRobinThread->exitAndWait(); - mRobinThread.clear(); - } - - free(mFrameBuffer.data); - mFrameBuffer.data = 0; - - close(mFD); - close(serverfd); - mFD = -1; - - // we'll try again - return true; -} - -// ---------------------------------------------------------------------------- - -RFBServer::ServerThread::ServerThread(const sp<RFBServer>& receiver) - : Thread(false), mReceiver(receiver) -{ - LOGD("RFB Server Thread created"); -} - -RFBServer::ServerThread::~ServerThread() -{ - LOGD("RFB Server Thread destroyed"); -} - -void RFBServer::ServerThread::onFirstRef() -{ - mUpdateBarrier.close(); - run("Robin"); -} - -status_t RFBServer::ServerThread::readyToRun() -{ - return NO_ERROR; -} - -void RFBServer::ServerThread::wake() -{ - mUpdateBarrier.open(); -} - -void RFBServer::ServerThread::exitAndWait() -{ - requestExit(); - mUpdateBarrier.open(); - requestExitAndWait(); -} - -bool RFBServer::ServerThread::threadLoop() -{ - sp<RFBServer> receiver(mReceiver.promote()); - if (receiver == 0) - return false; - - // wait for something to do - mUpdateBarrier.wait(); - - // we're asked to quit, abort everything - if (exitPending()) - return false; - - mUpdateBarrier.close(); - - // process updates - receiver->sendFrameBufferUpdates(); - return !exitPending(); -} - -// ---------------------------------------------------------------------------- - -void RFBServer::handshake(uint8_t major, uint8_t minor, uint32_t auth) -{ - ProtocolVersion protocolVersion(major, minor); - if( !write(protocolVersion) ) - return; - - if ( !read(protocolVersion) ) - return; - - int maj, min; - if ( protocolVersion.decode(maj, min) != NO_ERROR ) { - mStatus = -1; - return; - } - -#if DEBUG_MSG - LOGD("client protocol string: <%s>", (char*)protocolVersion.payload()); - LOGD("client wants protocol version %d.%d\n", maj, min); -#endif - - Authentication authentication(auth); - if( !write(authentication) ) - return; - - ClientInitialization clientInit; - if ( !read(clientInit) ) - return; - -#if DEBUG_MSG - LOGD("client initialization: sharedFlags = %d\n", clientInit.sharedFlags()); -#endif - - ServerInitialization serverInit("Android RFB"); - ServerInitialization::Payload& message(serverInit.message()); - message.framebufferWidth = htons(mFrameBuffer.width); - message.framebufferHeight = htons(mFrameBuffer.height); - message.serverPixelFormat.bitsPerPixel = 16; - message.serverPixelFormat.depth = 16; - message.serverPixelFormat.bigEndianFlag = 0; - message.serverPixelFormat.trueColorFlag = 1; - message.serverPixelFormat.redMax = htons((1<<5)-1); - message.serverPixelFormat.greenMax = htons((1<<6)-1); - message.serverPixelFormat.blueMax = htons((1<<5)-1); - message.serverPixelFormat.redShift = 11; - message.serverPixelFormat.greenShift = 5; - message.serverPixelFormat.blueShift = 0; - - mIoVec = new iovec[mFrameBuffer.height]; - - write(serverInit); -} - -void RFBServer::handleClientMessage(const ClientMessage& msg) -{ - switch(msg.type()) { - case SET_PIXEL_FORMAT: - handleSetPixelFormat(msg.messages().setPixelFormat); - break; - case SET_ENCODINGS: - handleSetEncodings(msg.messages().setEncodings); - break; - case FRAME_BUFFER_UPDATE_REQ: - handleFrameBufferUpdateReq(msg.messages().frameBufferUpdateRequest); - break; - case KEY_EVENT: - handleKeyEvent(msg.messages().keyEvent); - break; - } -} - -void RFBServer::handleSetPixelFormat(const SetPixelFormat& msg) -{ - if (!validatePixelFormat(msg.pixelFormat)) { - LOGE("The builtin VNC server only supports the RGB 565 pixel format"); - LOGD("requested pixel format:"); - LOGD("bitsPerPixel: %d", msg.pixelFormat.bitsPerPixel); - LOGD("depth: %d", msg.pixelFormat.depth); - LOGD("bigEndianFlag: %d", msg.pixelFormat.bigEndianFlag); - LOGD("trueColorFlag: %d", msg.pixelFormat.trueColorFlag); - LOGD("redmax: %d", ntohs(msg.pixelFormat.redMax)); - LOGD("bluemax: %d", ntohs(msg.pixelFormat.greenMax)); - LOGD("greenmax: %d", ntohs(msg.pixelFormat.blueMax)); - LOGD("redshift: %d", msg.pixelFormat.redShift); - LOGD("greenshift: %d", msg.pixelFormat.greenShift); - LOGD("blueshift: %d", msg.pixelFormat.blueShift); - mStatus = -1; - } -} - -bool RFBServer::validatePixelFormat(const PixelFormat& pf) -{ - if ((pf.bitsPerPixel != 16) || (pf.depth != 16)) - return false; - - if (pf.bigEndianFlag || !pf.trueColorFlag) - return false; - - if (ntohs(pf.redMax)!=0x1F || - ntohs(pf.greenMax)!=0x3F || - ntohs(pf.blueMax)!=0x1F) { - return false; - } - - if (pf.redShift!=11 || pf.greenShift!=5 || pf.blueShift!=0) - return false; - - return true; -} - -void RFBServer::handleSetEncodings(const SetEncodings& msg) -{ - /* From the RFB specification: - Sets the encoding types in which pixel data can be sent by the server. - The order of the encoding types given in this message is a hint by the - client as to its preference (the first encoding specified being most - preferred). The server may or may not choose to make use of this hint. - Pixel data may always be sent in raw encoding even if not specified - explicitly here. - */ - - LOGW("SetEncodings received. Only RAW is supported."); -} - -void RFBServer::handleFrameBufferUpdateReq(const FrameBufferUpdateRequest& msg) -{ -#if DEBUG_MSG - LOGD("handle FrameBufferUpdateRequest"); -#endif - - Rect r; - r.left = ntohs(msg.x); - r.top = ntohs(msg.y); - r.right = r.left + ntohs(msg.width); - r.bottom = r.top + ntohs(msg.height); - - Mutex::Autolock _l(mRegionLock); - mClientRegionRequest.set(r); - if (!msg.incremental) - mDirtyRegion.orSelf(r); - - mRobinThread->wake(); -} - -void RFBServer::handleKeyEvent(const KeyEvent& msg) -{ -#ifdef HAVE_ANDROID_OS - - int scancode = 0; - int code = ntohl(msg.key); - - if (code>='0' && code<='9') { - scancode = (code & 0xF) - 1; - if (scancode<0) scancode += 10; - scancode += KEY_1; - } else if (code>=0xFF50 && code<=0xFF58) { - static const uint16_t map[] = - { KEY_HOME, KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN, - KEY_SOFT1, KEY_SOFT2, KEY_END, 0 }; - scancode = map[code & 0xF]; - } else if (code>=0xFFE1 && code<=0xFFEE) { - static const uint16_t map[] = - { KEY_LEFTSHIFT, KEY_LEFTSHIFT, - KEY_COMPOSE, KEY_COMPOSE, - KEY_LEFTSHIFT, KEY_LEFTSHIFT, - 0,0, - KEY_LEFTALT, KEY_RIGHTALT, - 0, 0, 0, 0 }; - scancode = map[code & 0xF]; - } else if ((code>='A' && code<='Z') || (code>='a' && code<='z')) { - static const uint16_t map[] = { - KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, - KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, - KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, - KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, - KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z }; - scancode = map[(code & 0x5F) - 'A']; - } else { - switch (code) { - case 0x0003: scancode = KEY_CENTER; break; - case 0x0020: scancode = KEY_SPACE; break; - case 0x0023: scancode = KEY_SHARP; break; - case 0x0033: scancode = KEY_SHARP; break; - case 0x002C: scancode = KEY_COMMA; break; - case 0x003C: scancode = KEY_COMMA; break; - case 0x002E: scancode = KEY_DOT; break; - case 0x003E: scancode = KEY_DOT; break; - case 0x002F: scancode = KEY_SLASH; break; - case 0x003F: scancode = KEY_SLASH; break; - case 0x0032: scancode = KEY_EMAIL; break; - case 0x0040: scancode = KEY_EMAIL; break; - case 0xFF08: scancode = KEY_BACKSPACE; break; - case 0xFF1B: scancode = KEY_BACK; break; - case 0xFF09: scancode = KEY_TAB; break; - case 0xFF0D: scancode = KEY_ENTER; break; - case 0x002A: scancode = KEY_STAR; break; - case 0xFFBE: scancode = KEY_SEND; break; // F1 - case 0xFFBF: scancode = KEY_END; break; // F2 - case 0xFFC0: scancode = KEY_HOME; break; // F3 - case 0xFFC5: scancode = KEY_POWER; break; // F8 - } - } - -#if DEBUG_MSG - LOGD("handle KeyEvent 0x%08x, %d, scancode=%d\n", code, msg.downFlag, scancode); -#endif - - if (scancode) { - mEventInjector.injectKey(uint16_t(scancode), - msg.downFlag ? EventInjector::DOWN : EventInjector::UP); - } -#endif -} - -void RFBServer::waitForClientMessage(ClientMessage& msg) -{ - if ( !read(msg.payload(), 1) ) - return; - - switch(msg.type()) { - - case SET_PIXEL_FORMAT: - read(msg.payload(1), sizeof(SetPixelFormat)-1); - break; - - case FIX_COLOUR_MAP_ENTRIES: - mStatus = UNKNOWN_ERROR; - return; - - case SET_ENCODINGS: - { - if ( !read(msg.payload(1), sizeof(SetEncodings)-1) ) - return; - - size_t size = ntohs( msg.messages().setEncodings.numberOfEncodings ) * 4; - if (msg.resize(sizeof(SetEncodings) + size) != NO_ERROR) { - mStatus = NO_MEMORY; - return; - } - - if ( !read(msg.payload(sizeof(SetEncodings)), size) ) - return; - - break; - } - - case FRAME_BUFFER_UPDATE_REQ: - read(msg.payload(1), sizeof(FrameBufferUpdateRequest)-1); - break; - - case KEY_EVENT: - read(msg.payload(1), sizeof(KeyEvent)-1); - break; - - case POINTER_EVENT: - read(msg.payload(1), sizeof(PointerEvent)-1); - break; - - case CLIENT_CUT_TEXT: - { - if ( !read(msg.payload(1), sizeof(ClientCutText)-1) ) - return; - - size_t size = ntohl( msg.messages().clientCutText.length ); - if (msg.resize(sizeof(ClientCutText) + size) != NO_ERROR) { - mStatus = NO_MEMORY; - return; - } - - if ( !read(msg.payload(sizeof(SetEncodings)), size) ) - return; - - break; - } - - default: - LOGE("Unknown Message %d", msg.type()); - mStatus = UNKNOWN_ERROR; - return; - } -} - -// ---------------------------------------------------------------------------- - -bool RFBServer::write(const Message& msg) -{ - write(msg.payload(), msg.size()); - return alive(); -} - -bool RFBServer::read(Message& msg) -{ - read(msg.payload(), msg.size()); - return alive(); -} - -bool RFBServer::write(const void* buffer, int size) -{ - int wr = ::write(mFD, buffer, size); - if (wr != size) { - //LOGE("write(%d) error %d (%s)", size, wr, strerror(errno)); - mStatus = (wr == -1) ? errno : -1; - } - return alive(); -} - -bool RFBServer::read(void* buffer, int size) -{ - int rd = ::read(mFD, buffer, size); - if (rd != size) { - //LOGE("read(%d) error %d (%s)", size, rd, strerror(errno)); - mStatus = (rd == -1) ? errno : -1; - } - return alive(); -} - -bool RFBServer::alive() const -{ - return mStatus == 0; -} - -bool RFBServer::isConnected() const -{ - return alive(); -} - -// ---------------------------------------------------------------------------- - -void RFBServer::frameBufferUpdated(const GGLSurface& front, const Region& reg) -{ - Mutex::Autolock _l(mRegionLock); - - // update dirty region - mDirtyRegion.orSelf(reg); - - // remember the front-buffer - mFrontBuffer = front; - - // The client has not requested anything, don't do anything more - if (mClientRegionRequest.isEmpty()) - return; - - // wake the sending thread up - mRobinThread->wake(); -} - -void RFBServer::sendFrameBufferUpdates() -{ - Vector<Rect> rects; - size_t countRects; - GGLSurface fb; - - { // Scope for the lock - Mutex::Autolock _l(mRegionLock); - if (mFrontBuffer.data == 0) - return; - - const Region reg( mDirtyRegion.intersect(mClientRegionRequest) ); - if (reg.isEmpty()) - return; - - mDirtyRegion.subtractSelf(reg); - countRects = reg.rects(rects); - - // copy the frame-buffer so we can stay responsive - size_t bytesPerPix = bytesPerPixel(mFrameBuffer.format); - size_t bpr = mFrameBuffer.stride * bytesPerPix; - if (mFrameBuffer.data == 0) { - mFrameBuffer.data = (GGLubyte*)malloc(bpr * mFrameBuffer.height); - if (mFrameBuffer.data == 0) - return; - } - - memcpy(mFrameBuffer.data, mFrontBuffer.data, bpr*mFrameBuffer.height); - fb = mFrameBuffer; - } - - FrameBufferUpdate msgHeader; - msgHeader.type = 0; - msgHeader.numberOfRectangles = htons(countRects); - write(&msgHeader, sizeof(msgHeader)); - - Rectangle rectangle; - for (size_t i=0 ; i<countRects ; i++) { - const Rect& r = rects[i]; - rectangle.x = htons( r.left ); - rectangle.y = htons( r.top ); - rectangle.w = htons( r.width() ); - rectangle.h = htons( r.height() ); - rectangle.encoding = htons( SetEncodings::Raw ); - write(&rectangle, sizeof(rectangle)); - size_t h = r.height(); - size_t w = r.width(); - size_t bytesPerPix = bytesPerPixel(fb.format); - size_t bpr = fb.stride * bytesPerPix; - size_t bytes = w * bytesPerPix; - size_t offset = (r.top * bpr) + (r.left * bytesPerPix); - uint8_t* src = static_cast<uint8_t*>(fb.data) + offset; - iovec* iov = mIoVec; - while (h--) { - iov->iov_base = src; - iov->iov_len = bytes; - src += bpr; - iov++; - } - size_t iovcnt = iov - mIoVec; - int wr = ::writev(mFD, mIoVec, iovcnt); - if (wr < 0) { - //LOGE("write(%d) error %d (%s)", size, wr, strerror(errno)); - mStatus = errno; - } - } -} - -// ---------------------------------------------------------------------------- - -RFBServer::Message::Message(size_t size) - : mSize(size), mAllocatedSize(size) -{ - mPayload = malloc(size); -} - -RFBServer::Message::Message(void* payload, size_t size) - : mPayload(payload), mSize(size), mAllocatedSize(0) -{ -} - -RFBServer::Message::~Message() -{ - if (mAllocatedSize) - free(mPayload); -} - -status_t RFBServer::Message::resize(size_t size) -{ - if (size > mAllocatedSize) { - void* newp; - if (mAllocatedSize) { - newp = realloc(mPayload, size); - if (!newp) return NO_MEMORY; - } else { - newp = malloc(size); - if (!newp) return NO_MEMORY; - memcpy(newp, mPayload, mSize); - mAllocatedSize = size; - } - mPayload = newp; - } - mSize = size; - return NO_ERROR; -} - -// ---------------------------------------------------------------------------- - -RFBServer::EventInjector::EventInjector() - : mFD(-1) -{ -} - -RFBServer::EventInjector::~EventInjector() -{ -} - -void RFBServer::EventInjector::injectKey(uint16_t code, uint16_t value) -{ -#ifdef HAVE_ANDROID_OS - // XXX: we need to open the right event device - int version; - mFD = open("/dev/input/event0", O_RDWR); - ioctl(mFD, EVIOCGVERSION, &version); - - input_event ev; - memset(&ev, 0, sizeof(ev)); - ev.type = EV_KEY; - ev.code = code; - ev.value = value; - ::write(mFD, &ev, sizeof(ev)); - - close(mFD); - mFD = -1; -#endif -} - - -}; // namespace android - diff --git a/libs/surfaceflinger/RFBServer.h b/libs/surfaceflinger/RFBServer.h deleted file mode 100644 index 420912ed72..0000000000 --- a/libs/surfaceflinger/RFBServer.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_RFB_SERVER_H -#define ANDROID_RFB_SERVER_H - -#include <stdint.h> -#include <sys/types.h> -#include <sys/uio.h> -#include <unistd.h> -#include <arpa/inet.h> - -#include <utils/Errors.h> -#include <utils/threads.h> -#include <ui/Region.h> -#include <ui/PixelFormat.h> - -#include <pixelflinger/pixelflinger.h> - -#include "Barrier.h" - -namespace android { - -class SurfaceFlinger; - -class RFBServer : public Thread -{ -public: - RFBServer(uint32_t w, uint32_t h, android::PixelFormat format); - virtual ~RFBServer(); - - void frameBufferUpdated(const GGLSurface& front, const Region& reg); - bool isConnected() const; - -private: - typedef uint8_t card8; - typedef uint16_t card16; - typedef uint32_t card32; - - struct Message { - Message(size_t size); - virtual ~Message(); - void* payload(int offset=0) { - return static_cast<char*>(mPayload)+offset; - } - void const * payload(int offset=0) const { - return static_cast<char const *>(mPayload)+offset; - } - size_t size() const { return mSize; } - protected: - Message(void* payload, size_t size); - status_t resize(size_t size); - private: - void* mPayload; - size_t mSize; - size_t mAllocatedSize; - }; - - struct ProtocolVersion : public Message { - ProtocolVersion(uint8_t major, uint8_t minor) - : Message(&messageData, 12) { - char* p = static_cast<char*>(payload()); - snprintf(p, 13, "RFB %03u.%03u%c", major, minor, 0xA); - } - status_t decode(int& maj, int& min) { - char* p = static_cast<char*>(payload()); - int n = sscanf(p, "RFB %03u.%03u", &maj, &min); - return (n == 2) ? NO_ERROR : NOT_ENOUGH_DATA; - } - private: - char messageData[12+1]; - }; - - struct Authentication : public Message { - enum { Failed=0, None=1, Vnc=2 }; - Authentication(int auth) : Message(&messageData, 4) { - *static_cast<card32*>(payload()) = htonl(auth); - } - private: - card32 messageData; - }; - - struct ClientInitialization : public Message { - ClientInitialization() : Message(&messageData, 1) { } - int sharedFlags() { - return messageData; - } - private: - card8 messageData; - }; - - struct PixelFormat { - card8 bitsPerPixel; - card8 depth; - card8 bigEndianFlag; - card8 trueColorFlag; - card16 redMax; - card16 greenMax; - card16 blueMax; - card8 redShift; - card8 greenShift; - card8 blueShift; - uint8_t padding[3]; - } __attribute__((packed)); - - struct ServerInitialization : public Message { - ServerInitialization(char const * name) - : Message(sizeof(Payload) + strlen(name)) - { - const size_t nameLength = size() - sizeof(Payload); - message().nameLength = htonl(nameLength); - memcpy((char*)message().nameString, name,nameLength); - } - struct Payload { - card16 framebufferWidth; - card16 framebufferHeight; - PixelFormat serverPixelFormat; - card32 nameLength; - card8 nameString[0]; - } __attribute__((packed)); - Payload& message() { - return *static_cast<Payload*>(payload()); - } - }; - - // client messages... - - struct SetPixelFormat { - card8 type; - uint8_t padding[3]; - PixelFormat pixelFormat; - } __attribute__((packed)); - - struct SetEncodings { - enum { Raw=0, CoR=1, RRE=2, CoRRE=4, Hextile=5 }; - card8 type; - uint8_t padding; - card16 numberOfEncodings; - card32 encodings[0]; - } __attribute__((packed)); - - struct FrameBufferUpdateRequest { - card8 type; - card8 incremental; - card16 x; - card16 y; - card16 width; - card16 height; - } __attribute__((packed)); - - struct KeyEvent { - card8 type; - card8 downFlag; - uint8_t padding[2]; - card32 key; - } __attribute__((packed)); - - struct PointerEvent { - card8 type; - card8 buttonMask; - card16 x; - card16 y; - } __attribute__((packed)); - - struct ClientCutText { - card8 type; - uint8_t padding[3]; - card32 length; - card8 text[0]; - } __attribute__((packed)); - - union ClientMessages { - card8 type; - SetPixelFormat setPixelFormat; - SetEncodings setEncodings; - FrameBufferUpdateRequest frameBufferUpdateRequest; - KeyEvent keyEvent; - PointerEvent pointerEvent; - ClientCutText clientCutText; - }; - - struct Rectangle { - card16 x; - card16 y; - card16 w; - card16 h; - card32 encoding; - } __attribute__((packed)); - - struct FrameBufferUpdate { - card8 type; - uint8_t padding; - card16 numberOfRectangles; - Rectangle rectangles[0]; - } __attribute__((packed)); - - enum { - SET_PIXEL_FORMAT = 0, - FIX_COLOUR_MAP_ENTRIES = 1, - SET_ENCODINGS = 2, - FRAME_BUFFER_UPDATE_REQ = 3, - KEY_EVENT = 4, - POINTER_EVENT = 5, - CLIENT_CUT_TEXT = 6, - }; - - struct ClientMessage : public Message { - ClientMessage() - : Message(&messageData, sizeof(messageData)) { - } - const ClientMessages& messages() const { - return *static_cast<ClientMessages const *>(payload()); - } - const int type() const { - return messages().type; - } - status_t resize(size_t size) { - return Message::resize(size); - } - - ClientMessages messageData; - }; - - - class ServerThread : public Thread - { - friend class RFBServer; - public: - ServerThread(const sp<RFBServer>& receiver); - virtual ~ServerThread(); - void wake(); - void exitAndWait(); - private: - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void onFirstRef(); - wp<RFBServer> mReceiver; - bool (RFBServer::*mAction)(); - Barrier mUpdateBarrier; - }; - - class EventInjector { - public: - enum { UP=0, DOWN=1 }; - EventInjector(); - ~EventInjector(); - void injectKey(uint16_t code, uint16_t value); - private: - struct input_event { - struct timeval time; - uint16_t type; - uint16_t code; - uint32_t value; - }; - int mFD; - }; - - void handshake(uint8_t major, uint8_t minor, uint32_t auth); - void waitForClientMessage(ClientMessage& msg); - void handleClientMessage(const ClientMessage& msg); - void handleSetPixelFormat(const SetPixelFormat& msg); - void handleSetEncodings(const SetEncodings& msg); - void handleFrameBufferUpdateReq(const FrameBufferUpdateRequest& msg); - void handleKeyEvent(const KeyEvent& msg); - void sendFrameBufferUpdates(); - - bool validatePixelFormat(const PixelFormat& pf); - bool alive() const; - bool write(const Message& msg); - bool read(Message& msg); - - bool write(const void* buffer, int size); - bool read(void* buffer, int size); - - virtual bool threadLoop(); - virtual status_t readyToRun(); - virtual void onFirstRef(); - - sp<ServerThread> mRobinThread; - - int mFD; - int mStatus; - iovec* mIoVec; - - EventInjector mEventInjector; - - Mutex mRegionLock; - // This is the region requested by the client since the last - // time we updated it - Region mClientRegionRequest; - // This is the region of the screen that needs to be sent to the - // client since the last time we updated it. - // Typically this is the dirty region, but not necessarily, for - // instance if the client asked for a non incremental update. - Region mDirtyRegion; - - GGLSurface mFrameBuffer; - GGLSurface mFrontBuffer; -}; - -}; // namespace android - -#endif // ANDROID_RFB_SERVER_H diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp index 554e8e79b4..242d026882 100644 --- a/libs/surfaceflinger/SurfaceFlinger.cpp +++ b/libs/surfaceflinger/SurfaceFlinger.cpp @@ -53,20 +53,15 @@ #include "LayerBuffer.h" #include "LayerDim.h" #include "LayerBitmap.h" -#include "LayerScreenshot.h" +#include "LayerOrientationAnim.h" +#include "OrientationAnimation.h" #include "SurfaceFlinger.h" -#include "RFBServer.h" #include "VRamHeap.h" #include "DisplayHardware/DisplayHardware.h" #include "GPUHardware/GPUHardware.h" -// the VNC server even on local ports presents a significant -// thread as it can allow an application to control and "see" other -// applications, de-facto bypassing security permissions. -#define ENABLE_VNC_SERVER 0 - #define DISPLAY_COUNT 1 namespace android { @@ -185,6 +180,7 @@ SurfaceFlinger::SurfaceFlinger() mDeferReleaseConsole(false), mFreezeDisplay(false), mFreezeCount(0), + mFreezeDisplayTime(0), mDebugRegion(0), mDebugCpu(0), mDebugFps(0), @@ -225,6 +221,7 @@ void SurfaceFlinger::init() SurfaceFlinger::~SurfaceFlinger() { glDeleteTextures(1, &mWormholeTexName); + delete mOrientationAnimation; } copybit_device_t* SurfaceFlinger::getBlitEngine() const @@ -448,6 +445,8 @@ status_t SurfaceFlinger::readyToRun() * We're now ready to accept clients... */ + mOrientationAnimation = new OrientationAnimation(this); + // start CPU gauge display if (mDebugCpu) mCpuGauge = new CPUGauge(this, ms2ns(500)); @@ -456,9 +455,6 @@ status_t SurfaceFlinger::readyToRun() if (mDebugNoBootAnimation == false) mBootAnimation = new BootAnimation(this); - if (ENABLE_VNC_SERVER) - mRFBServer = new RFBServer(w, h, f); - return NO_ERROR; } @@ -472,17 +468,25 @@ void SurfaceFlinger::waitForEvent() { // wait for something to do if (UNLIKELY(isFrozen())) { - // wait 2 seconds - int err = mSyncObject.wait(ms2ns(3000)); + // wait 5 seconds + const nsecs_t freezeDisplayTimeout = ms2ns(5000); + const nsecs_t now = systemTime(); + if (mFreezeDisplayTime == 0) { + mFreezeDisplayTime = now; + } + nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime); + int err = (waitTime > 0) ? mSyncObject.wait(waitTime) : TIMED_OUT; if (err != NO_ERROR) { if (isFrozen()) { // we timed out and are still frozen LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d", mFreezeDisplay, mFreezeCount); mFreezeCount = 0; + mFreezeDisplay = false; } } } else { + mFreezeDisplayTime = 0; mSyncObject.wait(); } } @@ -556,11 +560,8 @@ bool SurfaceFlinger::threadLoop() void SurfaceFlinger::postFramebuffer() { - if (UNLIKELY(isFrozen())) { - // we are not allowed to draw, but pause a bit to make sure - // apps don't end up using the whole CPU, if they depend on - // surfaceflinger for synchronization. - usleep(8333); // 8.3ms ~ 120fps + const bool skip = mOrientationAnimation->run(); + if (UNLIKELY(skip)) { return; } @@ -571,18 +572,6 @@ void SurfaceFlinger::postFramebuffer() debugShowFPS(); } - if (UNLIKELY(ENABLE_VNC_SERVER && - mRFBServer!=0 && mRFBServer->isConnected())) { - if (!mSecureFrameBuffer) { - GGLSurface fb; - // backbufer, is going to become the front buffer really soon - hw.getDisplaySurface(&fb); - if (LIKELY(fb.data != 0)) { - mRFBServer->frameBufferUpdated(fb, mInvalidRegion); - } - } - } - hw.flip(mInvalidRegion); mInvalidRegion.clear(); @@ -685,18 +674,13 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) mVisibleRegionsDirty = true; mDirtyRegion.set(hw.bounds()); + + mOrientationAnimation->onOrientationChanged(); } if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) { // freezing or unfreezing the display -> trigger animation if needed mFreezeDisplay = mCurrentState.freezeDisplay; - const nsecs_t now = systemTime(); - if (mFreezeDisplay) { - mFreezeDisplayTime = now; - } else { - //LOGD("Screen was frozen for %llu us", - // ns2us(now-mFreezeDisplayTime)); - } } // some layers might have been removed, so @@ -875,19 +859,9 @@ void SurfaceFlinger::handleRepaint() uint32_t flags = hw.getFlags(); if (flags & DisplayHardware::BUFFER_PRESERVED) { - if (flags & DisplayHardware::COPY_BACK_EXTENSION) { - // yay. nothing to do here. - } else { - if (flags & DisplayHardware::UPDATE_ON_DEMAND) { - // we need to fully redraw the part that will be updated - mDirtyRegion.set(mInvalidRegion.bounds()); - } else { - // TODO: we only need te redraw the part that had been drawn - // the round before and is not drawn now - } - } + // here we assume DisplayHardware::flip()'s implementation + // performs the copy-back optimization. } else { - // COPY_BACK_EXTENSION makes no sense here if (flags & DisplayHardware::UPDATE_ON_DEMAND) { // we need to fully redraw the part that will be updated mDirtyRegion.set(mInvalidRegion.bounds()); @@ -1077,6 +1051,29 @@ void SurfaceFlinger::debugShowFPS() const // XXX: mFPS has the value we want } +status_t SurfaceFlinger::addLayer(LayerBase* layer) +{ + Mutex::Autolock _l(mStateLock); + addLayer_l(layer); + setTransactionFlags(eTransactionNeeded|eTraversalNeeded); + return NO_ERROR; +} + +status_t SurfaceFlinger::removeLayer(LayerBase* layer) +{ + Mutex::Autolock _l(mStateLock); + removeLayer_l(layer); + setTransactionFlags(eTransactionNeeded); + return NO_ERROR; +} + +status_t SurfaceFlinger::invalidateLayerVisibility(LayerBase* layer) +{ + layer->forceVisibilityTransaction(); + setTransactionFlags(eTraversalNeeded); + return NO_ERROR; +} + status_t SurfaceFlinger::addLayer_l(LayerBase* layer) { ssize_t i = mCurrentState.layersSortedByZ.add( @@ -1555,55 +1552,17 @@ status_t SurfaceFlinger::onTransact( status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags); if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) { - if (code == 1012) { - // take screen-shot of the front buffer - if (UNLIKELY(checkCallingPermission( - String16("android.permission.READ_FRAME_BUFFER")) == false)) - { // not allowed - LOGE("Permission Denial: " - "can't take screenshots from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - return PERMISSION_DENIED; - } - - if (UNLIKELY(mSecureFrameBuffer)) { - LOGE("A secure window is on screen: " - "can't take screenshots from pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - return PERMISSION_DENIED; - } - - LOGI("Taking a screenshot..."); - - LayerScreenshot* l = new LayerScreenshot(this, 0); - - Mutex::Autolock _l(mStateLock); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - l->initStates(hw.getWidth(), hw.getHeight(), 0); - l->setLayer(INT_MAX); - - addLayer_l(l); - setTransactionFlags(eTransactionNeeded|eTraversalNeeded); - - l->takeScreenshot(mStateLock, reply); - - removeLayer_l(l); - setTransactionFlags(eTransactionNeeded); - return NO_ERROR; - } else { - // HARDWARE_TEST stuff... - if (UNLIKELY(checkCallingPermission( - String16("android.permission.HARDWARE_TEST")) == false)) - { // not allowed - LOGE("Permission Denial: pid=%d, uid=%d\n", - IPCThreadState::self()->getCallingPid(), - IPCThreadState::self()->getCallingUid()); - return PERMISSION_DENIED; - } - int n; - switch (code) { + // HARDWARE_TEST stuff... + if (UNLIKELY(checkCallingPermission( + String16("android.permission.HARDWARE_TEST")) == false)) + { // not allowed + LOGE("Permission Denial: pid=%d, uid=%d\n", + IPCThreadState::self()->getCallingPid(), + IPCThreadState::self()->getCallingUid()); + return PERMISSION_DENIED; + } + int n; + switch (code) { case 1000: // SHOW_CPU n = data.readInt32(); mDebugCpu = n ? 1 : 0; @@ -1636,8 +1595,8 @@ status_t SurfaceFlinger::onTransact( const DisplayHardware& hw(graphicPlane(0).displayHardware()); mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe signalEvent(); - } - return NO_ERROR; + } + return NO_ERROR; case 1005: // ask GPU revoke mGPU->friendlyRevoke(); return NO_ERROR; @@ -1653,13 +1612,12 @@ status_t SurfaceFlinger::onTransact( reply->writeInt32(mDebugRegion); reply->writeInt32(mDebugBackground); return NO_ERROR; - case 1013: { // screenshot + case 1013: { Mutex::Autolock _l(mStateLock); const DisplayHardware& hw(graphicPlane(0).displayHardware()); reply->writeInt32(hw.getPageFlipCount()); } return NO_ERROR; - } } } return err; @@ -1813,10 +1771,33 @@ void GraphicPlane::setTransform(const Transform& tr) { mGlobalTransform = mOrientationTransform * mTransform; } -status_t GraphicPlane::setOrientation(int orientation) -{ +status_t GraphicPlane::orientationToTransfrom( + int orientation, int w, int h, Transform* tr) +{ float a, b, c, d, x, y; + switch (orientation) { + case ISurfaceComposer::eOrientationDefault: + a=1; b=0; c=0; d=1; x=0; y=0; + break; + case ISurfaceComposer::eOrientation90: + a=0; b=-1; c=1; d=0; x=w; y=0; + break; + case ISurfaceComposer::eOrientation180: + a=-1; b=0; c=0; d=-1; x=w; y=h; + break; + case ISurfaceComposer::eOrientation270: + a=0; b=1; c=-1; d=0; x=0; y=h; + break; + default: + return BAD_VALUE; + } + tr->set(a, b, c, d); + tr->set(x, y); + return NO_ERROR; +} +status_t GraphicPlane::setOrientation(int orientation) +{ const DisplayHardware& hw(displayHardware()); const float w = hw.getWidth(); const float h = hw.getHeight(); @@ -1830,30 +1811,21 @@ status_t GraphicPlane::setOrientation(int orientation) // If the rotation can be handled in hardware, this is where // the magic should happen. - - switch (orientation) { - case ISurfaceComposer::eOrientation90: - a=0; b=-1; c=1; d=0; x=w; y=0; - break; - case ISurfaceComposer::eOrientation180: - a=-1; b=0; c=0; d=-1; x=w; y=h; - break; - case ISurfaceComposer::eOrientation270: - a=0; b=1; c=-1; d=0; x=0; y=h; - break; - case 42: { + if (UNLIKELY(orientation == 42)) { + float a, b, c, d, x, y; const float r = (3.14159265f / 180.0f) * 42.0f; const float si = sinf(r); const float co = cosf(r); a=co; b=-si; c=si; d=co; x = si*(h*0.5f) + (1-co)*(w*0.5f); y =-si*(w*0.5f) + (1-co)*(h*0.5f); - } break; - default: - return BAD_VALUE; + mOrientationTransform.set(a, b, c, d); + mOrientationTransform.set(x, y); + } else { + GraphicPlane::orientationToTransfrom(orientation, w, h, + &mOrientationTransform); } - mOrientationTransform.set(a, b, c, d); - mOrientationTransform.set(x, y); + mGlobalTransform = mOrientationTransform * mTransform; return NO_ERROR; } diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h index a242f1aa01..f7d77640ae 100644 --- a/libs/surfaceflinger/SurfaceFlinger.h +++ b/libs/surfaceflinger/SurfaceFlinger.h @@ -35,11 +35,11 @@ #include <private/ui/LayerState.h> #include <private/ui/SurfaceFlingerSynchro.h> +#include "Barrier.h" +#include "BootAnimation.h" +#include "CPUGauge.h" #include "Layer.h" #include "Tokenizer.h" -#include "CPUGauge.h" -#include "BootAnimation.h" -#include "Barrier.h" struct copybit_device_t; struct overlay_device_t; @@ -48,16 +48,17 @@ namespace android { // --------------------------------------------------------------------------- -class BClient; class Client; +class BClient; class DisplayHardware; +class FreezeLock; class GPUHardwareInterface; class IGPUCallback; class Layer; class LayerBuffer; -class RFBServer; +class LayerOrientationAnim; +class OrientationAnimation; class SurfaceHeapManager; -class FreezeLock; typedef int32_t ClientID; @@ -110,6 +111,8 @@ private: class GraphicPlane { public: + static status_t orientationToTransfrom(int orientation, int w, int h, + Transform* tr); GraphicPlane(); ~GraphicPlane(); @@ -181,7 +184,12 @@ public: copybit_device_t* getBlitEngine() const; overlay_control_device_t* getOverlayEngine() const; + + status_t removeLayer(LayerBase* layer); + status_t addLayer(LayerBase* layer); + status_t invalidateLayerVisibility(LayerBase* layer); + private: friend class BClient; friend class LayerBase; @@ -337,7 +345,6 @@ private: sp<GPUHardwareInterface> mGPU; GLuint mWormholeTexName; sp<BootAnimation> mBootAnimation; - sp<RFBServer> mRFBServer; nsecs_t mBootTime; // Can only accessed from the main thread, these members @@ -352,6 +359,8 @@ private: bool mFreezeDisplay; int32_t mFreezeCount; nsecs_t mFreezeDisplayTime; + friend class OrientationAnimation; + OrientationAnimation* mOrientationAnimation; // access protected by mDebugLock mutable Mutex mDebugLock; diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp index 77bc5766be..0ccd71f0b8 100644 --- a/libs/surfaceflinger/VRamHeap.cpp +++ b/libs/surfaceflinger/VRamHeap.cpp @@ -35,8 +35,6 @@ #include <utils/MemoryHeapPmem.h> #include <utils/MemoryHeapBase.h> -#include <GLES/eglnatives.h> - #include "GPUHardware/GPUHardware.h" #include "SurfaceFlinger.h" #include "VRamHeap.h" diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp index 50c60084ad..b3cbda14fb 100644 --- a/libs/ui/Camera.cpp +++ b/libs/ui/Camera.cpp @@ -84,8 +84,10 @@ void Camera::init() mRawCallbackCookie = 0; mJpegCallback = 0; mJpegCallbackCookie = 0; - mFrameCallback = 0; - mFrameCallbackCookie = 0; + mPreviewCallback = 0; + mPreviewCallbackCookie = 0; + mRecordingCallback = 0; + mRecordingCallbackCookie = 0; mErrorCallback = 0; mErrorCallbackCookie = 0; mAutoFocusCallback = 0; @@ -108,6 +110,8 @@ sp<Camera> Camera::connect() if (c->mCamera != 0) { c->mCamera->asBinder()->linkToDeath(c); c->mStatus = NO_ERROR; + } else { + c.clear(); } return c; } @@ -184,6 +188,15 @@ status_t Camera::startPreview() return c->startPreview(); } +// start recording mode, must call setPreviewDisplay first +status_t Camera::startRecording() +{ + LOGV("startRecording"); + sp <ICamera> c = mCamera; + if (c == 0) return NO_INIT; + return c->startRecording(); +} + // stop preview mode void Camera::stopPreview() { @@ -193,6 +206,24 @@ void Camera::stopPreview() c->stopPreview(); } +// stop recording mode +void Camera::stopRecording() +{ + LOGV("stopRecording"); + sp <ICamera> c = mCamera; + if (c == 0) return; + c->stopRecording(); +} + +// release a recording frame +void Camera::releaseRecordingFrame(const sp<IMemory>& mem) +{ + LOGV("releaseRecordingFrame"); + sp <ICamera> c = mCamera; + if (c == 0) return; + c->releaseRecordingFrame(mem); +} + // get preview state bool Camera::previewEnabled() { @@ -202,6 +233,15 @@ bool Camera::previewEnabled() return c->previewEnabled(); } +// get recording state +bool Camera::recordingEnabled() +{ + LOGV("recordingEnabled"); + sp <ICamera> c = mCamera; + if (c == 0) return false; + return c->recordingEnabled(); +} + status_t Camera::autoFocus() { LOGV("autoFocus"); @@ -266,14 +306,21 @@ void Camera::setJpegCallback(frame_callback cb, void *cookie) mJpegCallbackCookie = cookie; } -void Camera::setFrameCallback(frame_callback cb, void *cookie, int frame_callback_flag) +void Camera::setPreviewCallback(frame_callback cb, void *cookie, int flag) { - LOGV("setFrameCallback"); - mFrameCallback = cb; - mFrameCallbackCookie = cookie; + LOGV("setPreviewCallback"); + mPreviewCallback = cb; + mPreviewCallbackCookie = cookie; sp <ICamera> c = mCamera; if (c == 0) return; - mCamera->setFrameCallbackFlag(frame_callback_flag); + mCamera->setPreviewCallbackFlag(flag); +} + +void Camera::setRecordingCallback(frame_callback cb, void *cookie) +{ + LOGV("setRecordingCallback"); + mRecordingCallback = cb; + mRecordingCallbackCookie = cookie; } void Camera::setErrorCallback(error_callback cb, void *cookie) @@ -316,12 +363,21 @@ void Camera::jpegCallback(const sp<IMemory>& picture) } } -// callback from camera service when video frame is ready -void Camera::frameCallback(const sp<IMemory>& frame) +// callback from camera service when preview frame is ready +void Camera::previewCallback(const sp<IMemory>& frame) { LOGV("frameCallback"); - if (mFrameCallback) { - mFrameCallback(frame, mFrameCallbackCookie); + if (mPreviewCallback) { + mPreviewCallback(frame, mPreviewCallbackCookie); + } +} + +// callback from camera service when a recording frame is ready +void Camera::recordingCallback(const sp<IMemory>& frame) +{ + LOGV("recordingCallback"); + if (mRecordingCallback) { + mRecordingCallback(frame, mRecordingCallbackCookie); } } diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp index 7ca77bbc53..6c258366fd 100644 --- a/libs/ui/CameraParameters.cpp +++ b/libs/ui/CameraParameters.cpp @@ -24,6 +24,9 @@ namespace android { +static const char* portrait = "portrait"; +static const char* landscape = "landscape"; + CameraParameters::CameraParameters() : mMap() { @@ -182,6 +185,23 @@ void CameraParameters::setPreviewFormat(const char *format) set("preview-format", format); } +int CameraParameters::getOrientation() const +{ + const char* orientation = get("orientation"); + if (orientation && !strcmp(orientation, portrait)) + return CAMERA_ORIENTATION_PORTRAIT; + return CAMERA_ORIENTATION_LANDSCAPE; +} + +void CameraParameters::setOrientation(int orientation) +{ + if (orientation == CAMERA_ORIENTATION_PORTRAIT) { + set("preview-format", portrait); + } else { + set("preview-format", landscape); + } +} + const char *CameraParameters::getPreviewFormat() const { return get("preview-format"); diff --git a/libs/ui/EGLDisplaySurface.cpp b/libs/ui/EGLDisplaySurface.cpp index 44258a8d2c..d06c98b9bb 100644 --- a/libs/ui/EGLDisplaySurface.cpp +++ b/libs/ui/EGLDisplaySurface.cpp @@ -42,7 +42,7 @@ #include <linux/msm_mdp.h> #endif -#include <GLES/egl.h> +#include <EGL/egl.h> #include <pixelflinger/format.h> @@ -71,8 +71,6 @@ EGLDisplaySurface::EGLDisplaySurface() egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef; egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef; egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers; - egl_native_window_t::setSwapRectangle = &EGLDisplaySurface::hook_setSwapRectangle; - egl_native_window_t::nextBuffer = &EGLDisplaySurface::hook_nextBuffer; egl_native_window_t::connect = 0; egl_native_window_t::disconnect = 0; @@ -136,15 +134,6 @@ uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) { EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); return that->swapBuffers(); } -uint32_t EGLDisplaySurface::hook_nextBuffer(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - return that->nextBuffer(); -} -void EGLDisplaySurface::hook_setSwapRectangle(NativeWindowType window, - int l, int t, int w, int h) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->setSwapRectangle(l, t, w, h); -} void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h) { @@ -249,15 +238,6 @@ int32_t EGLDisplaySurface::getPageFlipCount() const return mPageFlipCount; } -uint32_t EGLDisplaySurface::nextBuffer() -{ - // update the address of the buffer to draw to next - const GGLSurface& buffer = mFb[mIndex]; - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - return 0; -} - void EGLDisplaySurface::copyFrontToBack(const Region& copyback) { #if HAVE_ANDROID_OS @@ -318,6 +298,59 @@ void EGLDisplaySurface::copyFrontToBack(const Region& copyback) } } +void EGLDisplaySurface::copyFrontToImage(const copybit_image_t& dst) +{ +#if HAVE_ANDROID_OS + if (mBlitEngine) { + copybit_image_t src = { + w: egl_native_window_t::stride, + h: egl_native_window_t::height, + format: egl_native_window_t::format, + offset: mFb[mIndex].data - mFb[0].data, + base: (void*)egl_native_window_t::base, + fd: egl_native_window_t::fd + }; + region_iterator it(Region(Rect( + egl_native_window_t::width, egl_native_window_t::height))); + mBlitEngine->blit(mBlitEngine, &dst, &src, &it); + } else +#endif + { + uint8_t* const screen_src = mFb[ mIndex].data; + const size_t bpp = bytesPerPixel(egl_native_window_t::format); + const size_t bpr = egl_native_window_t::stride * bpp; + memcpy((char*)dst.base + dst.offset, screen_src, + bpr*egl_native_window_t::height); + } +} + +void EGLDisplaySurface::copyBackToImage(const copybit_image_t& dst) +{ +#if HAVE_ANDROID_OS + if (mBlitEngine) { + copybit_image_t src = { + w: egl_native_window_t::stride, + h: egl_native_window_t::height, + format: egl_native_window_t::format, + offset: mFb[1-mIndex].data - mFb[0].data, + base: (void*)egl_native_window_t::base, + fd: egl_native_window_t::fd + }; + region_iterator it(Region(Rect( + egl_native_window_t::width, egl_native_window_t::height))); + mBlitEngine->blit(mBlitEngine, &dst, &src, &it); + } else +#endif + { + uint8_t* const screen_src = mFb[1-mIndex].data; + const size_t bpp = bytesPerPixel(egl_native_window_t::format); + const size_t bpr = egl_native_window_t::stride * bpp; + memcpy((char*)dst.base + dst.offset, screen_src, + bpr*egl_native_window_t::height); + } +} + + status_t EGLDisplaySurface::mapFrameBuffer() { char const * const device_template[] = { diff --git a/libs/ui/EGLNativeWindowSurface.cpp b/libs/ui/EGLNativeWindowSurface.cpp index d55fb7090f..f1071cf909 100644 --- a/libs/ui/EGLNativeWindowSurface.cpp +++ b/libs/ui/EGLNativeWindowSurface.cpp @@ -28,7 +28,7 @@ #include <ui/DisplayInfo.h> #include <ui/Rect.h> -#include <GLES/egl.h> +#include <EGL/egl.h> #include <pixelflinger/format.h> @@ -48,8 +48,6 @@ EGLNativeWindowSurface::EGLNativeWindowSurface(const sp<Surface>& surface) egl_native_window_t::incRef = &EGLNativeWindowSurface::hook_incRef; egl_native_window_t::decRef = &EGLNativeWindowSurface::hook_decRef; egl_native_window_t::swapBuffers = &EGLNativeWindowSurface::hook_swapBuffers; - egl_native_window_t::nextBuffer = &EGLNativeWindowSurface::hook_nextBuffer; - egl_native_window_t::setSwapRectangle = &EGLNativeWindowSurface::hook_setSwapRectangle; egl_native_window_t::connect = &EGLNativeWindowSurface::hook_connect; egl_native_window_t::disconnect = &EGLNativeWindowSurface::hook_disconnect; @@ -98,18 +96,6 @@ uint32_t EGLNativeWindowSurface::hook_swapBuffers(NativeWindowType window) return that->swapBuffers(); } -uint32_t EGLNativeWindowSurface::hook_nextBuffer(NativeWindowType window) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - return that->nextBuffer(); -} - -void EGLNativeWindowSurface::hook_setSwapRectangle(NativeWindowType window, int l, int t, int w, int h) -{ - EGLNativeWindowSurface* that = static_cast<EGLNativeWindowSurface*>(window); - that->setSwapRectangle(l, t, w, h); -} - void EGLNativeWindowSurface::setSwapRectangle(int l, int t, int w, int h) { mSurface->setSwapRectangle(Rect(l, t, l+w, t+h)); @@ -138,17 +124,6 @@ uint32_t EGLNativeWindowSurface::swapBuffers() return 0; } -uint32_t EGLNativeWindowSurface::nextBuffer() -{ - const sp<Surface>& surface(mSurface); - Surface::SurfaceInfo info; - surface->nextBuffer(&info); - // update the address of the buffer to draw to next - egl_native_window_t::base = intptr_t(info.base); - egl_native_window_t::offset = intptr_t(info.bits) - intptr_t(info.base); - return 0; -} - void EGLNativeWindowSurface::connect() { if (!mConnected) { diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp index 700aa3a8ad..3b29b094db 100644 --- a/libs/ui/EventHub.cpp +++ b/libs/ui/EventHub.cpp @@ -71,10 +71,11 @@ static inline int max(int v1, int v2) EventHub::device_t::device_t(int32_t _id, const char* _path) : id(_id), path(_path), classes(0) - , layoutMap(new KeyLayoutMap()), next(NULL) { + , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), next(NULL) { } EventHub::device_t::~device_t() { + delete [] keyBitmask; delete layoutMap; } @@ -403,6 +404,36 @@ bool EventHub::openPlatformInput(void) return true; } +/* + * Inspect the known devices to determine whether physical keys exist for the given + * framework-domain key codes. + */ +bool EventHub::hasKeys(size_t numCodes, int32_t* keyCodes, uint8_t* outFlags) { + for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) { + outFlags[codeIndex] = 0; + + // check each available hardware device for support for this keycode + Vector<int32_t> scanCodes; + for (int n = 0; (n < mFDCount) && (outFlags[codeIndex] == 0); n++) { + if (mDevices[n]) { + status_t err = mDevices[n]->layoutMap->findScancodes(keyCodes[codeIndex], &scanCodes); + if (!err) { + // check the possible scan codes identified by the layout map against the + // map of codes actually emitted by the driver + for (size_t sc = 0; sc < scanCodes.size(); sc++) { + if (test_bit(scanCodes[sc], mDevices[n]->keyBitmask)) { + outFlags[codeIndex] = 1; + break; + } + } + } + } + } + } + + return true; +} + // ---------------------------------------------------------------------------- int EventHub::open_device(const char *deviceName) @@ -527,6 +558,16 @@ int EventHub::open_device(const char *deviceName) break; } } + if ((device->classes & CLASS_KEYBOARD) != 0) { + device->keyBitmask = new uint8_t[(KEY_MAX+1)/8]; + if (device->keyBitmask != NULL) { + memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask)); + } else { + delete device; + LOGE("out of memory allocating key bitmask"); + return -1; + } + } } if (test_bit(BTN_MOUSE, key_bitmask)) { uint8_t rel_bitmask[(REL_MAX+1)/8]; diff --git a/libs/ui/ICamera.cpp b/libs/ui/ICamera.cpp index 7b0922ec72..ab0fef1489 100644 --- a/libs/ui/ICamera.cpp +++ b/libs/ui/ICamera.cpp @@ -28,7 +28,7 @@ namespace android { enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, SET_PREVIEW_DISPLAY, - SET_FRAME_CALLBACK_FLAG, + SET_PREVIEW_CALLBACK_FLAG, START_PREVIEW, STOP_PREVIEW, AUTO_FOCUS, @@ -38,7 +38,11 @@ enum { CONNECT, LOCK, UNLOCK, - PREVIEW_ENABLED + PREVIEW_ENABLED, + START_RECORDING, + STOP_RECORDING, + RECORDING_ENABLED, + RELEASE_RECORDING_FRAME, }; class BpCamera: public BpInterface<ICamera> @@ -69,15 +73,15 @@ public: return reply.readInt32(); } - // set the frame callback flag to affect how the received frames from - // preview are handled. - void setFrameCallbackFlag(int frame_callback_flag) + // set the preview callback flag to affect how the received frames from + // preview are handled. See Camera.h for details. + void setPreviewCallbackFlag(int flag) { - LOGV("setFrameCallbackFlag(%d)", frame_callback_flag); + LOGV("setPreviewCallbackFlag(%d)", flag); Parcel data, reply; data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); - data.writeInt32(frame_callback_flag); - remote()->transact(SET_FRAME_CALLBACK_FLAG, data, &reply); + data.writeInt32(flag); + remote()->transact(SET_PREVIEW_CALLBACK_FLAG, data, &reply); } // start preview mode, must call setPreviewDisplay first @@ -90,6 +94,16 @@ public: return reply.readInt32(); } + // start recording mode, must call setPreviewDisplay first + status_t startRecording() + { + LOGV("startRecording"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(START_RECORDING, data, &reply); + return reply.readInt32(); + } + // stop preview mode void stopPreview() { @@ -99,6 +113,24 @@ public: remote()->transact(STOP_PREVIEW, data, &reply); } + // stop recording mode + void stopRecording() + { + LOGV("stopRecording"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(STOP_RECORDING, data, &reply); + } + + void releaseRecordingFrame(const sp<IMemory>& mem) + { + LOGV("releaseRecordingFrame"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + data.writeStrongBinder(mem->asBinder()); + remote()->transact(RELEASE_RECORDING_FRAME, data, &reply); + } + // check preview state bool previewEnabled() { @@ -109,6 +141,16 @@ public: return reply.readInt32(); } + // check recording state + bool recordingEnabled() + { + LOGV("recordingEnabled"); + Parcel data, reply; + data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); + remote()->transact(RECORDING_ENABLED, data, &reply); + return reply.readInt32(); + } + // auto focus status_t autoFocus() { @@ -202,11 +244,11 @@ status_t BnCamera::onTransact( reply->writeInt32(setPreviewDisplay(surface)); return NO_ERROR; } break; - case SET_FRAME_CALLBACK_FLAG: { - LOGV("SET_FRAME_CALLBACK_TYPE"); + case SET_PREVIEW_CALLBACK_FLAG: { + LOGV("SET_PREVIEW_CALLBACK_TYPE"); CHECK_INTERFACE(ICamera, data, reply); - int frame_callback_flag = data.readInt32(); - setFrameCallbackFlag(frame_callback_flag); + int callback_flag = data.readInt32(); + setPreviewCallbackFlag(callback_flag); return NO_ERROR; } break; case START_PREVIEW: { @@ -215,18 +257,43 @@ status_t BnCamera::onTransact( reply->writeInt32(startPreview()); return NO_ERROR; } break; + case START_RECORDING: { + LOGV("START_RECORDING"); + CHECK_INTERFACE(ICamera, data, reply); + reply->writeInt32(startRecording()); + return NO_ERROR; + } break; case STOP_PREVIEW: { LOGV("STOP_PREVIEW"); CHECK_INTERFACE(ICamera, data, reply); stopPreview(); return NO_ERROR; } break; + case STOP_RECORDING: { + LOGV("STOP_RECORDING"); + CHECK_INTERFACE(ICamera, data, reply); + stopRecording(); + return NO_ERROR; + } break; + case RELEASE_RECORDING_FRAME: { + LOGV("RELEASE_RECORDING_FRAME"); + CHECK_INTERFACE(ICamera, data, reply); + sp<IMemory> mem = interface_cast<IMemory>(data.readStrongBinder()); + releaseRecordingFrame(mem); + return NO_ERROR; + } break; case PREVIEW_ENABLED: { LOGV("PREVIEW_ENABLED"); CHECK_INTERFACE(ICamera, data, reply); reply->writeInt32(previewEnabled()); return NO_ERROR; } break; + case RECORDING_ENABLED: { + LOGV("RECORDING_ENABLED"); + CHECK_INTERFACE(ICamera, data, reply); + reply->writeInt32(recordingEnabled()); + return NO_ERROR; + } break; case AUTO_FOCUS: { LOGV("AUTO_FOCUS"); CHECK_INTERFACE(ICamera, data, reply); diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp index c5d6d52f4d..4bec9d2ae6 100644 --- a/libs/ui/ICameraClient.cpp +++ b/libs/ui/ICameraClient.cpp @@ -28,9 +28,10 @@ enum { SHUTTER_CALLBACK = IBinder::FIRST_CALL_TRANSACTION, RAW_CALLBACK, JPEG_CALLBACK, - FRAME_CALLBACK, + PREVIEW_CALLBACK, ERROR_CALLBACK, - AUTOFOCUS_CALLBACK + AUTOFOCUS_CALLBACK, + RECORDING_CALLBACK, }; class BpCameraClient: public BpInterface<ICameraClient> @@ -70,14 +71,24 @@ public: remote()->transact(JPEG_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } - // callback from camera service to app with video frame data - void frameCallback(const sp<IMemory>& frame) + // callback from camera service to app with preview frame data + void previewCallback(const sp<IMemory>& frame) { - LOGV("frameCallback"); + LOGV("previewCallback"); Parcel data, reply; data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); data.writeStrongBinder(frame->asBinder()); - remote()->transact(FRAME_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); + remote()->transact(PREVIEW_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); + } + + // callback from camera service to app with recording frame data + void recordingCallback(const sp<IMemory>& frame) + { + LOGV("recordingCallback"); + Parcel data, reply; + data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); + data.writeStrongBinder(frame->asBinder()); + remote()->transact(RECORDING_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } // callback from camera service to app to report error @@ -135,11 +146,18 @@ status_t BnCameraClient::onTransact( jpegCallback(picture); return NO_ERROR; } break; - case FRAME_CALLBACK: { - LOGV("FRAME_CALLBACK"); + case PREVIEW_CALLBACK: { + LOGV("PREVIEW_CALLBACK"); + CHECK_INTERFACE(ICameraClient, data, reply); + sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder()); + previewCallback(frame); + return NO_ERROR; + } break; + case RECORDING_CALLBACK: { + LOGV("RECORDING_CALLBACK"); CHECK_INTERFACE(ICameraClient, data, reply); sp<IMemory> frame = interface_cast<IMemory>(data.readStrongBinder()); - frameCallback(frame); + recordingCallback(frame); return NO_ERROR; } break; case ERROR_CALLBACK: { diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp index 6f3cd4776b..d5e9f812a4 100644 --- a/libs/ui/ISurface.cpp +++ b/libs/ui/ISurface.cpp @@ -27,12 +27,33 @@ namespace android { -enum { - REGISTER_BUFFERS = IBinder::FIRST_CALL_TRANSACTION, - UNREGISTER_BUFFERS, - POST_BUFFER, // one-way transaction - CREATE_OVERLAY, -}; +ISurface::BufferHeap::BufferHeap() + : w(0), h(0), hor_stride(0), ver_stride(0), format(0), + transform(0), flags(0) +{ +} + +ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h, + int32_t hor_stride, int32_t ver_stride, + PixelFormat format, const sp<IMemoryHeap>& heap) + : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride), + format(format), transform(0), flags(0), heap(heap) +{ +} + +ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h, + int32_t hor_stride, int32_t ver_stride, + PixelFormat format, uint32_t transform, uint32_t flags, + const sp<IMemoryHeap>& heap) + : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride), + format(format), transform(transform), flags(flags), heap(heap) +{ +} + + +ISurface::BufferHeap::~BufferHeap() +{ +} class BpSurface : public BpInterface<ISurface> { @@ -42,17 +63,18 @@ public: { } - virtual status_t registerBuffers(int w, int h, int hstride, int vstride, - PixelFormat format, const sp<IMemoryHeap>& heap) + virtual status_t registerBuffers(const BufferHeap& buffers) { Parcel data, reply; data.writeInterfaceToken(ISurface::getInterfaceDescriptor()); - data.writeInt32(w); - data.writeInt32(h); - data.writeInt32(hstride); - data.writeInt32(vstride); - data.writeInt32(format); - data.writeStrongBinder(heap->asBinder()); + data.writeInt32(buffers.w); + data.writeInt32(buffers.h); + data.writeInt32(buffers.hor_stride); + data.writeInt32(buffers.ver_stride); + data.writeInt32(buffers.format); + data.writeInt32(buffers.transform); + data.writeInt32(buffers.flags); + data.writeStrongBinder(buffers.heap->asBinder()); remote()->transact(REGISTER_BUFFERS, data, &reply); status_t result = reply.readInt32(); return result; @@ -102,13 +124,16 @@ status_t BnSurface::onTransact( switch(code) { case REGISTER_BUFFERS: { CHECK_INTERFACE(ISurface, data, reply); - int w = data.readInt32(); - int h = data.readInt32(); - int hs= data.readInt32(); - int vs= data.readInt32(); - PixelFormat f = data.readInt32(); - sp<IMemoryHeap> heap(interface_cast<IMemoryHeap>(data.readStrongBinder())); - status_t err = registerBuffers(w,h,hs,vs,f,heap); + BufferHeap buffer; + buffer.w = data.readInt32(); + buffer.h = data.readInt32(); + buffer.hor_stride = data.readInt32(); + buffer.ver_stride= data.readInt32(); + buffer.format = data.readInt32(); + buffer.transform = data.readInt32(); + buffer.flags = data.readInt32(); + buffer.heap = interface_cast<IMemoryHeap>(data.readStrongBinder()); + status_t err = registerBuffers(buffer); reply->writeInt32(err); return NO_ERROR; } break; diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp index 605c8aef93..b65ed9736b 100644 --- a/libs/ui/PixelFormat.cpp +++ b/libs/ui/PixelFormat.cpp @@ -19,6 +19,18 @@ namespace android { +size_t PixelFormatInfo::getScanlineSize(unsigned int width) const +{ + size_t size; + if ((components >= 6) && (components <= 8)) { + // YCbCr formats are differents. + size = (width * bitsPerPixel)>>3; + } else { + size = width * bytesPerPixel; + } + return size; +} + ssize_t bytesPerPixel(PixelFormat format) { PixelFormatInfo info; @@ -47,7 +59,25 @@ status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info) if (!valid) { return BAD_INDEX; } - + + #define COMPONENT(name) \ + case GGL_##name: info->components = PixelFormatInfo::name; break; + + switch (i->components) { + COMPONENT(ALPHA) + COMPONENT(RGB) + COMPONENT(RGBA) + COMPONENT(LUMINANCE) + COMPONENT(LUMINANCE_ALPHA) + COMPONENT(Y_CB_CR_SP) + COMPONENT(Y_CB_CR_P) + COMPONENT(Y_CB_CR_I) + default: + return BAD_INDEX; + } + + #undef COMPONENT + info->format = format; info->bytesPerPixel = i->size; info->bitsPerPixel = i->bitsPerPixel; @@ -59,6 +89,7 @@ status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info) info->l_green = i->gl; info->h_blue = i->bh; info->l_blue = i->bl; + return NO_ERROR; } diff --git a/libs/utils/CallStack.cpp b/libs/utils/CallStack.cpp index 26fb22abc0..2fdaa71186 100644 --- a/libs/utils/CallStack.cpp +++ b/libs/utils/CallStack.cpp @@ -120,13 +120,18 @@ class MapInfo { char name[]; }; - const char *map_to_name(uint64_t pc, const char* def) { + const char *map_to_name(uint64_t pc, const char* def, uint64_t* start) { mapinfo* mi = getMapInfoList(); while(mi) { - if ((pc >= mi->start) && (pc < mi->end)) + if ((pc >= mi->start) && (pc < mi->end)) { + if (start) + *start = mi->start; return mi->name; + } mi = mi->next; } + if (start) + *start = 0; return def; } @@ -183,8 +188,15 @@ public: } } - static const char *mapAddressToName(const void* pc, const char* def) { - return sMapInfo.map_to_name((uint64_t)pc, def); + static const char *mapAddressToName(const void* pc, const char* def, + void const** start) + { + uint64_t s; + char const* name = sMapInfo.map_to_name(uint64_t(uintptr_t(pc)), def, &s); + if (start) { + *start = (void*)s; + } + return name; } }; @@ -297,8 +309,9 @@ String8 CallStack::toStringSingleLevel(const char* prefix, int32_t level) const res.append(name); res.append(tmp2); } else { - name = MapInfo::mapAddressToName(ip, "<unknown>"); - snprintf(tmp, 256, "pc %p %s", ip, name); + void const* start = 0; + name = MapInfo::mapAddressToName(ip, "<unknown>", &start); + snprintf(tmp, 256, "pc %08lx %s", uintptr_t(ip)-uintptr_t(start), name); res.append(tmp); } res.append("\n"); diff --git a/libs/utils/Parcel.cpp b/libs/utils/Parcel.cpp index 2962b25aea..4225e67283 100644 --- a/libs/utils/Parcel.cpp +++ b/libs/utils/Parcel.cpp @@ -658,15 +658,20 @@ status_t Parcel::writeNativeHandle(const native_handle& handle) status_t err; err = writeInt32(handle.numFds); if (err != NO_ERROR) return err; - + err = writeInt32(handle.numInts); if (err != NO_ERROR) return err; - + for (int i=0 ; err==NO_ERROR && i<handle.numFds ; i++) err = writeDupFileDescriptor(handle.data[i]); - + + if (err != NO_ERROR) { + LOGD("write native handle, write dup fd failed"); + return err; + } + err = write(handle.data + handle.numFds, sizeof(int)*handle.numInts); - + return err; } diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp index 5a09fb44a0..2ad3bfe8b8 100644 --- a/libs/utils/ResourceTypes.cpp +++ b/libs/utils/ResourceTypes.cpp @@ -176,7 +176,9 @@ size_t Res_png_9patch::serializedSize() void* Res_png_9patch::serialize() { - void* newData = malloc(serializedSize()); + // Use calloc since we're going to leave a few holes in the data + // and want this to run cleanly under valgrind + void* newData = calloc(1, serializedSize()); serialize(newData); return newData; } @@ -1736,7 +1738,7 @@ bool ResTable::getResourceName(uint32_t resID, resource_name* outName) const } ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, - uint32_t* outSpecFlags) const + uint32_t* outSpecFlags, ResTable_config* outConfig) const { if (mError != NO_ERROR) { return mError; @@ -1809,7 +1811,7 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag (const Res_value*)(((const uint8_t*)type) + offset); ResTable_config thisConfig; thisConfig.copyFromDtoH(type->config); - + if (outSpecFlags != NULL) { if (typeClass->typeSpecFlags != NULL) { *outSpecFlags |= dtohl(typeClass->typeSpecFlags[e]); @@ -1834,6 +1836,9 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag outValue->res0 = bestValue->res0; outValue->dataType = bestValue->dataType; outValue->data = dtohl(bestValue->data); + if (outConfig != NULL) { + *outConfig = bestItem; + } TABLE_NOISY(size_t len; printf("Found value: pkg=%d, type=%d, str=%s, int=%d\n", bestPackage->header->index, @@ -3147,13 +3152,13 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString, const char16_t* pos = s; while (pos < end && !failed) { const char16_t* start = pos; - end++; + pos++; while (pos < end && *pos != '|') { pos++; } - //printf("Looking for: %s\n", String8(start, pos-start).string()); + //printf("Looking for: %s\n", String8(start, pos-start).string()); const bag_entry* bagi = bag; - ssize_t i; + ssize_t i; for (i=0; i<cnt; i++, bagi++) { if (!Res_INTERNALID(bagi->map.name.ident)) { //printf("Trying attr #%08x\n", bagi->map.name.ident); @@ -3181,7 +3186,7 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString, } unlockBag(bag); if (!failed) { - //printf("Final flag value: 0x%lx\n", outValue->data); + //printf("Final flag value: 0x%lx\n", outValue->data); return true; } } @@ -3189,7 +3194,7 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString, if (fromAccessor) { if (accessor->getAttributeFlags(attrID, s, len, outValue)) { - //printf("Final flag value: 0x%lx\n", outValue->data); + //printf("Final flag value: 0x%lx\n", outValue->data); return true; } } @@ -3484,7 +3489,7 @@ ssize_t ResTable::getEntry( ResTable_config thisConfig; thisConfig.copyFromDtoH(thisType->config); - + TABLE_GETENTRY(LOGI("Match entry 0x%x in type 0x%x (sz 0x%x): imsi:%d/%d=%d/%d lang:%c%c=%c%c cnt:%c%c=%c%c " "orien:%d=%d touch:%d=%d density:%d=%d key:%d=%d inp:%d=%d nav:%d=%d w:%d=%d h:%d=%d\n", entryIndex, typeIndex+1, dtohl(thisType->config.size), diff --git a/libs/utils/String16.cpp b/libs/utils/String16.cpp index 1f81cadb7a..aef67f22af 100644 --- a/libs/utils/String16.cpp +++ b/libs/utils/String16.cpp @@ -244,7 +244,6 @@ void terminate_string16() // --------------------------------------------------------------------------- -// Note: not dealing with generating surrogate pairs. static char16_t* allocFromUTF8(const char* in, size_t len) { if (len == 0) return getEmptyString(); @@ -255,7 +254,10 @@ static char16_t* allocFromUTF8(const char* in, size_t len) while (p < end) { chars++; - p += utf8_char_len(*p); + int utf8len = utf8_char_len(*p); + uint32_t codepoint = utf8_to_utf32((const uint8_t*)p, utf8len); + if (codepoint > 0xFFFF) chars++; // this will be a surrogate pair in utf16 + p += utf8len; } SharedBuffer* buf = SharedBuffer::alloc((chars+1)*sizeof(char16_t)); @@ -265,7 +267,19 @@ static char16_t* allocFromUTF8(const char* in, size_t len) char16_t* d = str; while (p < end) { size_t len = utf8_char_len(*p); - *d++ = (char16_t)utf8_to_utf32((const uint8_t*)p, len); + uint32_t codepoint = utf8_to_utf32((const uint8_t*)p, len); + + // Convert the UTF32 codepoint to one or more UTF16 codepoints + if (codepoint <= 0xFFFF) { + // Single UTF16 character + *d++ = (char16_t) codepoint; + } else { + // Multiple UTF16 characters with surrogates + codepoint = codepoint - 0x10000; + *d++ = (char16_t) ((codepoint >> 10) + 0xD800); + *d++ = (char16_t) ((codepoint & 0x3FF) + 0xDC00); + } + p += len; } *d = 0; @@ -388,7 +402,7 @@ status_t String16::setTo(const char16_t* other, size_t len) ->editResize((len+1)*sizeof(char16_t)); if (buf) { char16_t* str = (char16_t*)buf->data(); - memcpy(str, other, len*sizeof(char16_t)); + memmove(str, other, len*sizeof(char16_t)); str[len] = 0; mString = str; return NO_ERROR; diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp index ab843f6e79..c50d343a73 100644 --- a/libs/utils/String8.cpp +++ b/libs/utils/String8.cpp @@ -317,8 +317,10 @@ status_t String8::real_append(const char* other, size_t otherLen) ->editResize(myLen+otherLen+1); if (buf) { char* str = (char*)buf->data(); - memcpy(str+myLen, other, otherLen+1); mString = str; + str += myLen; + memcpy(str, other, otherLen); + str[otherLen] = '\0'; return NO_ERROR; } return NO_MEMORY; diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp index 74271ba3b4..9287c0bbab 100644 --- a/libs/utils/Threads.cpp +++ b/libs/utils/Threads.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +// #define LOG_NDEBUG 0 #define LOG_TAG "libutils.threads" #include <utils/threads.h> @@ -838,146 +839,6 @@ void Condition::broadcast() #error "condition variables not supported on this platform" #endif - -/* - * =========================================================================== - * ReadWriteLock class - * =========================================================================== - */ - -#if 0 -#pragma mark - -#pragma mark ReadWriteLock -#endif - -/* - * Add a reader. Readers are nice. They share. - */ -void ReadWriteLock::lockForRead() -{ - mLock.lock(); - while (mNumWriters > 0) { - LOG(LOG_DEBUG, "thread", "+++ lockForRead: waiting\n"); - mReadWaiter.wait(mLock); - } - assert(mNumWriters == 0); - mNumReaders++; -#if defined(PRINT_RENDER_TIMES) - if (mNumReaders == 1) - mDebugTimer.start(); -#endif - mLock.unlock(); -} - -/* - * Try to add a reader. If it doesn't work right away, return "false". - */ -bool ReadWriteLock::tryLockForRead() -{ - mLock.lock(); - if (mNumWriters > 0) { - mLock.unlock(); - return false; - } - assert(mNumWriters == 0); - mNumReaders++; -#if defined(PRINT_RENDER_TIMES) - if (mNumReaders == 1) - mDebugTimer.start(); -#endif - mLock.unlock(); - return true; -} - -/* - * Remove a reader. - */ -void ReadWriteLock::unlockForRead() -{ - mLock.lock(); - if (mNumReaders == 0) { - LOG(LOG_WARN, "thread", - "WARNING: unlockForRead requested, but not locked\n"); - return; - } - assert(mNumReaders > 0); - assert(mNumWriters == 0); - mNumReaders--; - if (mNumReaders == 0) { // last reader? -#if defined(PRINT_RENDER_TIMES) - mDebugTimer.stop(); - printf(" rdlk held %.3f msec\n", - (double) mDebugTimer.durationUsecs() / 1000.0); -#endif - //printf("+++ signaling writers (if any)\n"); - mWriteWaiter.signal(); // wake one writer (if any) - } - mLock.unlock(); -} - -/* - * Add a writer. This requires exclusive access to the object. - */ -void ReadWriteLock::lockForWrite() -{ - mLock.lock(); - while (mNumReaders > 0 || mNumWriters > 0) { - LOG(LOG_DEBUG, "thread", "+++ lockForWrite: waiting\n"); - mWriteWaiter.wait(mLock); - } - assert(mNumReaders == 0); - assert(mNumWriters == 0); - mNumWriters++; -#if defined(PRINT_RENDER_TIMES) - mDebugTimer.start(); -#endif - mLock.unlock(); -} - -/* - * Try to add a writer. If it doesn't work right away, return "false". - */ -bool ReadWriteLock::tryLockForWrite() -{ - mLock.lock(); - if (mNumReaders > 0 || mNumWriters > 0) { - mLock.unlock(); - return false; - } - assert(mNumReaders == 0); - assert(mNumWriters == 0); - mNumWriters++; -#if defined(PRINT_RENDER_TIMES) - mDebugTimer.start(); -#endif - mLock.unlock(); - return true; -} - -/* - * Remove a writer. - */ -void ReadWriteLock::unlockForWrite() -{ - mLock.lock(); - if (mNumWriters == 0) { - LOG(LOG_WARN, "thread", - "WARNING: unlockForWrite requested, but not locked\n"); - return; - } - assert(mNumWriters == 1); - mNumWriters--; -#if defined(PRINT_RENDER_TIMES) - mDebugTimer.stop(); - //printf(" wrlk held %.3f msec\n", - // (double) mDebugTimer.durationUsecs() / 1000.0); -#endif - // mWriteWaiter.signal(); // should other writers get first dibs? - //printf("+++ signaling readers (if any)\n"); - mReadWaiter.broadcast(); // wake all readers (if any) - mLock.unlock(); -} - // ---------------------------------------------------------------------------- #if 0 @@ -1025,6 +886,8 @@ status_t Thread::run(const char* name, int32_t priority, size_t stack) // hold a strong reference on ourself mHoldSelf = this; + mRunning = true; + bool res; if (mCanCallJava) { res = createThreadEtc(_threadLoop, @@ -1038,14 +901,16 @@ status_t Thread::run(const char* name, int32_t priority, size_t stack) mStatus = UNKNOWN_ERROR; // something happened! mRunning = false; mThread = thread_id_t(-1); + mHoldSelf.clear(); // "this" may have gone away after this. + + return UNKNOWN_ERROR; } - if (mStatus < 0) { - // something happened, don't leak - mHoldSelf.clear(); - } - - return mStatus; + // Do not refer to mStatus here: The thread is already running (may, in fact + // already have exited with a valid mStatus result). The NO_ERROR indication + // here merely indicates successfully starting the thread and does not + // imply successful termination/execution. + return NO_ERROR; } int Thread::_threadLoop(void* user) @@ -1055,20 +920,32 @@ int Thread::_threadLoop(void* user) wp<Thread> weak(strong); self->mHoldSelf.clear(); - // we're about to run... - self->mStatus = self->readyToRun(); - if (self->mStatus!=NO_ERROR || self->mExitPending) { - // pretend the thread never started... - self->mExitPending = false; - self->mRunning = false; - return 0; - } - - // thread is running now - self->mRunning = true; + bool first = true; do { - bool result = self->threadLoop(); + bool result; + if (first) { + first = false; + self->mStatus = self->readyToRun(); + result = (self->mStatus == NO_ERROR); + + if (result && !self->mExitPending) { + // Binder threads (and maybe others) rely on threadLoop + // running at least once after a successful ::readyToRun() + // (unless, of course, the thread has already been asked to exit + // at that point). + // This is because threads are essentially used like this: + // (new ThreadSubclass())->run(); + // The caller therefore does not retain a strong reference to + // the thread and the thread would simply disappear after the + // successful ::readyToRun() call instead of entering the + // threadLoop at least once. + result = self->threadLoop(); + } + } else { + result = self->threadLoop(); + } + if (result == false || self->mExitPending) { self->mExitPending = true; self->mLock.lock(); @@ -1095,24 +972,23 @@ void Thread::requestExit() status_t Thread::requestExitAndWait() { - if (mStatus == OK) { - - if (mThread == getThreadId()) { - LOGW( - "Thread (this=%p): don't call waitForExit() from this " - "Thread object's thread. It's a guaranteed deadlock!", - this); - return WOULD_BLOCK; - } - - requestExit(); + if (mThread == getThreadId()) { + LOGW( + "Thread (this=%p): don't call waitForExit() from this " + "Thread object's thread. It's a guaranteed deadlock!", + this); - Mutex::Autolock _l(mLock); - while (mRunning == true) { - mThreadExitedCondition.wait(mLock); - } - mExitPending = false; + return WOULD_BLOCK; } + + requestExit(); + + Mutex::Autolock _l(mLock); + while (mRunning == true) { + mThreadExitedCondition.wait(mLock); + } + mExitPending = false; + return mStatus; } diff --git a/opengl/include/EGL/egl.h b/opengl/include/EGL/egl.h new file mode 100644 index 0000000000..c269976f4a --- /dev/null +++ b/opengl/include/EGL/egl.h @@ -0,0 +1,330 @@ +/* -*- mode: c; tab-width: 8; -*- */ +/* vi: set sw=4 ts=8: */ +/* Reference version of egl.h for EGL 1.4. + * $Revision: 7244 $ on $Date: 2009-01-20 17:06:59 -0800 (Tue, 20 Jan 2009) $ + */ + +/* +** Copyright (c) 2007-2009 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#ifndef __egl_h_ +#define __egl_h_ + +/* All platform-dependent types and macro boilerplate (such as EGLAPI + * and EGLAPIENTRY) should go in eglplatform.h. + */ +#include <EGL/eglplatform.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* EGL Types */ +/* EGLint is defined in eglplatform.h */ +typedef unsigned int EGLBoolean; +typedef unsigned int EGLenum; +typedef void *EGLConfig; +typedef void *EGLContext; +typedef void *EGLDisplay; +typedef void *EGLSurface; +typedef void *EGLClientBuffer; + +/* EGL Versioning */ +#define EGL_VERSION_1_0 1 +#define EGL_VERSION_1_1 1 +#define EGL_VERSION_1_2 1 +#define EGL_VERSION_1_3 1 +#define EGL_VERSION_1_4 1 + +/* EGL Enumerants. Bitmasks and other exceptional cases aside, most + * enums are assigned unique values starting at 0x3000. + */ + +/* EGL aliases */ +#define EGL_FALSE 0 +#define EGL_TRUE 1 + +/* Out-of-band handle values */ +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) +#define EGL_NO_CONTEXT ((EGLContext)0) +#define EGL_NO_DISPLAY ((EGLDisplay)0) +#define EGL_NO_SURFACE ((EGLSurface)0) + +/* Out-of-band attribute value */ +#define EGL_DONT_CARE ((EGLint)-1) + +/* Errors / GetError return values */ +#define EGL_SUCCESS 0x3000 +#define EGL_NOT_INITIALIZED 0x3001 +#define EGL_BAD_ACCESS 0x3002 +#define EGL_BAD_ALLOC 0x3003 +#define EGL_BAD_ATTRIBUTE 0x3004 +#define EGL_BAD_CONFIG 0x3005 +#define EGL_BAD_CONTEXT 0x3006 +#define EGL_BAD_CURRENT_SURFACE 0x3007 +#define EGL_BAD_DISPLAY 0x3008 +#define EGL_BAD_MATCH 0x3009 +#define EGL_BAD_NATIVE_PIXMAP 0x300A +#define EGL_BAD_NATIVE_WINDOW 0x300B +#define EGL_BAD_PARAMETER 0x300C +#define EGL_BAD_SURFACE 0x300D +#define EGL_CONTEXT_LOST 0x300E /* EGL 1.1 - IMG_power_management */ + +/* Reserved 0x300F-0x301F for additional errors */ + +/* Config attributes */ +#define EGL_BUFFER_SIZE 0x3020 +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BLUE_SIZE 0x3022 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_RED_SIZE 0x3024 +#define EGL_DEPTH_SIZE 0x3025 +#define EGL_STENCIL_SIZE 0x3026 +#define EGL_CONFIG_CAVEAT 0x3027 +#define EGL_CONFIG_ID 0x3028 +#define EGL_LEVEL 0x3029 +#define EGL_MAX_PBUFFER_HEIGHT 0x302A +#define EGL_MAX_PBUFFER_PIXELS 0x302B +#define EGL_MAX_PBUFFER_WIDTH 0x302C +#define EGL_NATIVE_RENDERABLE 0x302D +#define EGL_NATIVE_VISUAL_ID 0x302E +#define EGL_NATIVE_VISUAL_TYPE 0x302F +#define EGL_PRESERVED_RESOURCES 0x3030 +#define EGL_SAMPLES 0x3031 +#define EGL_SAMPLE_BUFFERS 0x3032 +#define EGL_SURFACE_TYPE 0x3033 +#define EGL_TRANSPARENT_TYPE 0x3034 +#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 +#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 +#define EGL_TRANSPARENT_RED_VALUE 0x3037 +#define EGL_NONE 0x3038 /* Attrib list terminator */ +#define EGL_BIND_TO_TEXTURE_RGB 0x3039 +#define EGL_BIND_TO_TEXTURE_RGBA 0x303A +#define EGL_MIN_SWAP_INTERVAL 0x303B +#define EGL_MAX_SWAP_INTERVAL 0x303C +#define EGL_LUMINANCE_SIZE 0x303D +#define EGL_ALPHA_MASK_SIZE 0x303E +#define EGL_COLOR_BUFFER_TYPE 0x303F +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_MATCH_NATIVE_PIXMAP 0x3041 /* Pseudo-attribute (not queryable) */ +#define EGL_CONFORMANT 0x3042 + +/* Reserved 0x3041-0x304F for additional config attributes */ + +/* Config attribute values */ +#define EGL_SLOW_CONFIG 0x3050 /* EGL_CONFIG_CAVEAT value */ +#define EGL_NON_CONFORMANT_CONFIG 0x3051 /* EGL_CONFIG_CAVEAT value */ +#define EGL_TRANSPARENT_RGB 0x3052 /* EGL_TRANSPARENT_TYPE value */ +#define EGL_RGB_BUFFER 0x308E /* EGL_COLOR_BUFFER_TYPE value */ +#define EGL_LUMINANCE_BUFFER 0x308F /* EGL_COLOR_BUFFER_TYPE value */ + +/* More config attribute values, for EGL_TEXTURE_FORMAT */ +#define EGL_NO_TEXTURE 0x305C +#define EGL_TEXTURE_RGB 0x305D +#define EGL_TEXTURE_RGBA 0x305E +#define EGL_TEXTURE_2D 0x305F + +/* Config attribute mask bits */ +#define EGL_PBUFFER_BIT 0x0001 /* EGL_SURFACE_TYPE mask bits */ +#define EGL_PIXMAP_BIT 0x0002 /* EGL_SURFACE_TYPE mask bits */ +#define EGL_WINDOW_BIT 0x0004 /* EGL_SURFACE_TYPE mask bits */ +#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 /* EGL_SURFACE_TYPE mask bits */ +#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 /* EGL_SURFACE_TYPE mask bits */ +#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 /* EGL_SURFACE_TYPE mask bits */ +#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 /* EGL_SURFACE_TYPE mask bits */ + +#define EGL_OPENGL_ES_BIT 0x0001 /* EGL_RENDERABLE_TYPE mask bits */ +#define EGL_OPENVG_BIT 0x0002 /* EGL_RENDERABLE_TYPE mask bits */ +#define EGL_OPENGL_ES2_BIT 0x0004 /* EGL_RENDERABLE_TYPE mask bits */ +#define EGL_OPENGL_BIT 0x0008 /* EGL_RENDERABLE_TYPE mask bits */ + +/* QueryString targets */ +#define EGL_VENDOR 0x3053 +#define EGL_VERSION 0x3054 +#define EGL_EXTENSIONS 0x3055 +#define EGL_CLIENT_APIS 0x308D + +/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */ +#define EGL_HEIGHT 0x3056 +#define EGL_WIDTH 0x3057 +#define EGL_LARGEST_PBUFFER 0x3058 +#define EGL_TEXTURE_FORMAT 0x3080 +#define EGL_TEXTURE_TARGET 0x3081 +#define EGL_MIPMAP_TEXTURE 0x3082 +#define EGL_MIPMAP_LEVEL 0x3083 +#define EGL_RENDER_BUFFER 0x3086 +#define EGL_VG_COLORSPACE 0x3087 +#define EGL_VG_ALPHA_FORMAT 0x3088 +#define EGL_HORIZONTAL_RESOLUTION 0x3090 +#define EGL_VERTICAL_RESOLUTION 0x3091 +#define EGL_PIXEL_ASPECT_RATIO 0x3092 +#define EGL_SWAP_BEHAVIOR 0x3093 +#define EGL_MULTISAMPLE_RESOLVE 0x3099 + +/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */ +#define EGL_BACK_BUFFER 0x3084 +#define EGL_SINGLE_BUFFER 0x3085 + +/* OpenVG color spaces */ +#define EGL_VG_COLORSPACE_sRGB 0x3089 /* EGL_VG_COLORSPACE value */ +#define EGL_VG_COLORSPACE_LINEAR 0x308A /* EGL_VG_COLORSPACE value */ + +/* OpenVG alpha formats */ +#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B /* EGL_ALPHA_FORMAT value */ +#define EGL_VG_ALPHA_FORMAT_PRE 0x308C /* EGL_ALPHA_FORMAT value */ + +/* Constant scale factor by which fractional display resolutions & + * aspect ratio are scaled when queried as integer values. + */ +#define EGL_DISPLAY_SCALING 10000 + +/* Unknown display resolution/aspect ratio */ +#define EGL_UNKNOWN ((EGLint)-1) + +/* Back buffer swap behaviors */ +#define EGL_BUFFER_PRESERVED 0x3094 /* EGL_SWAP_BEHAVIOR value */ +#define EGL_BUFFER_DESTROYED 0x3095 /* EGL_SWAP_BEHAVIOR value */ + +/* CreatePbufferFromClientBuffer buffer types */ +#define EGL_OPENVG_IMAGE 0x3096 + +/* QueryContext targets */ +#define EGL_CONTEXT_CLIENT_TYPE 0x3097 + +/* CreateContext attributes */ +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 + +/* Multisample resolution behaviors */ +#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A /* EGL_MULTISAMPLE_RESOLVE value */ +#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B /* EGL_MULTISAMPLE_RESOLVE value */ + +/* BindAPI/QueryAPI targets */ +#define EGL_OPENGL_ES_API 0x30A0 +#define EGL_OPENVG_API 0x30A1 +#define EGL_OPENGL_API 0x30A2 + +/* GetCurrentSurface targets */ +#define EGL_DRAW 0x3059 +#define EGL_READ 0x305A + +/* WaitNative engines */ +#define EGL_CORE_NATIVE_ENGINE 0x305B + +/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */ +#define EGL_COLORSPACE EGL_VG_COLORSPACE +#define EGL_ALPHA_FORMAT EGL_VG_ALPHA_FORMAT +#define EGL_COLORSPACE_sRGB EGL_VG_COLORSPACE_sRGB +#define EGL_COLORSPACE_LINEAR EGL_VG_COLORSPACE_LINEAR +#define EGL_ALPHA_FORMAT_NONPRE EGL_VG_ALPHA_FORMAT_NONPRE +#define EGL_ALPHA_FORMAT_PRE EGL_VG_ALPHA_FORMAT_PRE + +/* EGL extensions must request enum blocks from the Khronos + * API Registrar, who maintains the enumerant registry. Submit + * a bug in Khronos Bugzilla against task "Registry". + */ + + + +/* EGL Functions */ + +EGLAPI EGLint EGLAPIENTRY eglGetError(void); + +EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id); +EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor); +EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy); + +EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name); + +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, + EGLint config_size, EGLint *num_config); +EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, + EGLConfig *configs, EGLint config_size, + EGLint *num_config); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, + EGLint attribute, EGLint *value); + +EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, + EGLNativeWindowType win, + const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, + EGLNativePixmapType pixmap, + const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, + EGLint attribute, EGLint *value); + +EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api); +EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void); + +EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void); + +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void); + +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer( + EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, + EGLConfig config, const EGLint *attrib_list); + +EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, + EGLint attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); + + +EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval); + + +EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, + EGLContext share_context, + const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, + EGLSurface read, EGLContext ctx); + +EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void); +EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw); +EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, + EGLint attribute, EGLint *value); + +EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, + EGLNativePixmapType target); + +/* This is a generic function pointer type, whose name indicates it must + * be cast to the proper type *and calling convention* before use. + */ +typedef void (*__eglMustCastToProperFunctionPointerType)(void); + +/* Now, define eglGetProcAddress using the generic function ptr. type */ +EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY + eglGetProcAddress(const char *procname); + +#ifdef __cplusplus +} +#endif + +#endif /* __egl_h_ */ diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h new file mode 100644 index 0000000000..25cfcb832f --- /dev/null +++ b/opengl/include/EGL/eglext.h @@ -0,0 +1,138 @@ +#ifndef __eglext_h_ +#define __eglext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2007-2009 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +#include <EGL/eglplatform.h> + +/*************************************************************/ + +/* Header file version number */ +/* Current version at http://www.khronos.org/registry/egl/ */ +/* $Revision: 7244 $ on $Date: 2009-01-20 17:06:59 -0800 (Tue, 20 Jan 2009) $ */ +#define EGL_EGLEXT_VERSION 3 + +#ifndef EGL_KHR_config_attribs +#define EGL_KHR_config_attribs 1 +#define EGL_CONFORMANT_KHR 0x3042 /* EGLConfig attribute */ +#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 /* EGL_SURFACE_TYPE bitfield */ +#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 /* EGL_SURFACE_TYPE bitfield */ +#endif + +#ifndef EGL_KHR_lock_surface +#define EGL_KHR_lock_surface 1 +#define EGL_READ_SURFACE_BIT_KHR 0x0001 /* EGL_LOCK_USAGE_HINT_KHR bitfield */ +#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 /* EGL_LOCK_USAGE_HINT_KHR bitfield */ +#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 /* EGL_SURFACE_TYPE bitfield */ +#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 /* EGL_SURFACE_TYPE bitfield */ +#define EGL_MATCH_FORMAT_KHR 0x3043 /* EGLConfig attribute */ +#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 /* EGL_MATCH_FORMAT_KHR value */ +#define EGL_FORMAT_RGB_565_KHR 0x30C1 /* EGL_MATCH_FORMAT_KHR value */ +#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 /* EGL_MATCH_FORMAT_KHR value */ +#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 /* EGL_MATCH_FORMAT_KHR value */ +#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 /* eglLockSurfaceKHR attribute */ +#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 /* eglLockSurfaceKHR attribute */ +#define EGL_BITMAP_POINTER_KHR 0x30C6 /* eglQuerySurface attribute */ +#define EGL_BITMAP_PITCH_KHR 0x30C7 /* eglQuerySurface attribute */ +#define EGL_BITMAP_ORIGIN_KHR 0x30C8 /* eglQuerySurface attribute */ +#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 /* eglQuerySurface attribute */ +#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA /* eglQuerySurface attribute */ +#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB /* eglQuerySurface attribute */ +#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC /* eglQuerySurface attribute */ +#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD /* eglQuerySurface attribute */ +#define EGL_LOWER_LEFT_KHR 0x30CE /* EGL_BITMAP_ORIGIN_KHR value */ +#define EGL_UPPER_LEFT_KHR 0x30CF /* EGL_BITMAP_ORIGIN_KHR value */ +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface); +#endif + +#ifndef EGL_KHR_image +#define EGL_KHR_image 1 +#define EGL_NATIVE_PIXMAP_KHR 0x30B0 /* eglCreateImageKHR target */ +typedef void *EGLImageKHR; +#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image); +#endif + +#ifndef EGL_KHR_vg_parent_image +#define EGL_KHR_vg_parent_image 1 +#define EGL_VG_PARENT_IMAGE_KHR 0x30BA /* eglCreateImageKHR target */ +#endif + +#ifndef EGL_KHR_gl_texture_2D_image +#define EGL_KHR_gl_texture_2D_image 1 +#define EGL_GL_TEXTURE_2D_KHR 0x30B1 /* eglCreateImageKHR target */ +#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC /* eglCreateImageKHR attribute */ +#endif + +#ifndef EGL_KHR_gl_texture_cubemap_image +#define EGL_KHR_gl_texture_cubemap_image 1 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 /* eglCreateImageKHR target */ +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 /* eglCreateImageKHR target */ +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 /* eglCreateImageKHR target */ +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 /* eglCreateImageKHR target */ +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 /* eglCreateImageKHR target */ +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 /* eglCreateImageKHR target */ +#endif + +#ifndef EGL_KHR_gl_texture_3D_image +#define EGL_KHR_gl_texture_3D_image 1 +#define EGL_GL_TEXTURE_3D_KHR 0x30B2 /* eglCreateImageKHR target */ +#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD /* eglCreateImageKHR attribute */ +#endif + +#ifndef EGL_KHR_gl_renderbuffer_image +#define EGL_KHR_gl_renderbuffer_image 1 +#define EGL_GL_RENDERBUFFER_KHR 0x30B9 /* eglCreateImageKHR target */ +#endif + +#ifndef EGL_KHR_image_base +#define EGL_KHR_image_base 1 +/* Most interfaces defined by EGL_KHR_image_pixmap above */ +#define EGL_IMAGE_PRESERVED_KHR 0x30D2 /* eglCreateImageKHR attribute */ +#endif + +#ifndef EGL_KHR_image_pixmap +#define EGL_KHR_image_pixmap 1 +/* Interfaces defined by EGL_KHR_image above */ +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/GLES/eglnatives.h b/opengl/include/EGL/eglnatives.h index 1cd57d0684..21622dc5a6 100644 --- a/include/GLES/eglnatives.h +++ b/opengl/include/EGL/eglnatives.h @@ -22,23 +22,8 @@ #ifdef __cplusplus extern "C" { #endif -/*****************************************************************************/ - -struct egl_native_window_t; -struct egl_native_pixmap_t; - - -typedef struct egl_native_window_t* NativeWindowType; -typedef struct egl_native_pixmap_t* NativePixmapType; -typedef void* NativeDisplayType; - -/* - * This a convenience function to create a NativeWindowType surface - * that maps to the whole screen - * This function is actually implemented in libui.so - */ -NativeWindowType android_createDisplaySurface(); +/*****************************************************************************/ /* flags returned from swapBuffer */ #define EGL_NATIVES_FLAG_SIZE_CHANGED 0x00000001 @@ -151,48 +136,46 @@ struct egl_native_window_t /* * Hook called by EGL to hold a reference on this structure */ - void (*incRef)(NativeWindowType window); + void (*incRef)(struct egl_native_window_t* window); /* * Hook called by EGL to release a reference on this structure */ - void (*decRef)(NativeWindowType window); + void (*decRef)(struct egl_native_window_t* window); /* * Hook called by EGL to perform a page flip. This function * may update the size attributes above, in which case it returns * the EGL_NATIVES_FLAG_SIZE_CHANGED bit set. */ - uint32_t (*swapBuffers)(NativeWindowType window); + uint32_t (*swapBuffers)(struct egl_native_window_t* window); /* - * Hook called by EGL to set the swap rectangle. this hook can be - * null (operation not supported) + * Reserved for future use. MUST BE ZERO. */ - void (*setSwapRectangle)(NativeWindowType window, int l, int t, int w, int h); + void (*reserved_proc_0)(void); /* * Reserved for future use. MUST BE ZERO. */ - void (*reserved_proc_0)(void); - + void (*reserved_proc_1)(void); /* - * Hook called by EGL to retrieve the next buffer to render into. - * This call updates this structure. + * Reserved for future use. MUST BE ZERO. */ - uint32_t (*nextBuffer)(NativeWindowType window); + void (*reserved_proc_2)(void); + /* * Hook called by EGL when the native surface is associated to EGL * (eglCreateWindowSurface). Can be NULL. */ - void (*connect)(NativeWindowType window); + void (*connect)(struct egl_native_window_t* window); /* * Hook called by EGL when eglDestroySurface is called. Can be NULL. */ - void (*disconnect)(NativeWindowType window); + void (*disconnect)(struct egl_native_window_t* window); /* * Reserved for future use. MUST BE ZERO. @@ -224,6 +207,17 @@ struct egl_native_pixmap_t /*****************************************************************************/ +/* + * This a convenience function to create a NativeWindowType surface + * that maps to the whole screen + * This function is actually implemented in libui.so + */ + +struct egl_native_window_t* android_createDisplaySurface(); + +/*****************************************************************************/ + + /* * OEM's egl's library (libhgl.so) must imlement these hooks to allocate * the GPU memory they need diff --git a/opengl/include/EGL/eglplatform.h b/opengl/include/EGL/eglplatform.h new file mode 100644 index 0000000000..ac0090102c --- /dev/null +++ b/opengl/include/EGL/eglplatform.h @@ -0,0 +1,117 @@ +#ifndef __eglplatform_h_ +#define __eglplatform_h_ + +/* +** Copyright (c) 2007-2009 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Platform-specific types and definitions for egl.h + * $Revision: 7244 $ on $Date: 2009-01-20 17:06:59 -0800 (Tue, 20 Jan 2009) $ + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "EGL" component "Registry". + */ + +#include <KHR/khrplatform.h> + +/* Macros used in EGL function prototype declarations. + * + * EGL functions should be prototyped as: + * + * EGLAPI return-type EGLAPIENTRY eglFunction(arguments); + * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments); + * + * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h + */ + +#ifndef EGLAPI +#define EGLAPI KHRONOS_APICALL +#endif + +#define EGLAPIENTRY KHRONOS_APIENTRY +#define EGLAPIENTRYP KHRONOS_APIENTRY* + +/* The types NativeDisplayType, NativeWindowType, and NativePixmapType + * are aliases of window-system-dependent types, such as X Display * or + * Windows Device Context. They must be defined in platform-specific + * code below. The EGL-prefixed versions of Native*Type are the same + * types, renamed in EGL 1.3 so all types in the API start with "EGL". + */ + +#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include <windows.h> + +typedef HDC EGLNativeDisplayType; +typedef HBITMAP EGLNativePixmapType; +typedef HWND EGLNativeWindowType; + +#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ + +typedef int EGLNativeDisplayType; +typedef void *EGLNativeWindowType; +typedef void *EGLNativePixmapType; + +#elif defined(__unix__) && !defined(ANDROID) + +/* X11 (tentative) */ +#include <X11/Xlib.h> +#include <X11/Xutil.h> + +typedef Display *EGLNativeDisplayType; +typedef Pixmap EGLNativePixmapType; +typedef Window EGLNativeWindowType; + + +#elif defined(ANDROID) + +#include <EGL/eglnatives.h> + +typedef struct egl_native_window_t* EGLNativeWindowType; +typedef struct egl_native_pixmap_t* EGLNativePixmapType; +typedef void* EGLNativeDisplayType; + +#else +#error "Platform not recognized" +#endif + +/* EGL 1.2 types, renamed for consistency in EGL 1.3 */ +typedef EGLNativeDisplayType NativeDisplayType; +typedef EGLNativePixmapType NativePixmapType; +typedef EGLNativeWindowType NativeWindowType; + + +/* Define EGLint. This must be a signed integral type large enough to contain + * all legal attribute names and values passed into and out of EGL, whether + * their type is boolean, bitmask, enumerant (symbolic constant), integer, + * handle, or other. While in general a 32-bit integer will suffice, if + * handles are 64 bit types, then EGLint should be defined as a signed 64-bit + * integer type. + */ +typedef khronos_int32_t EGLint; + +#endif /* __eglplatform_h */ diff --git a/opengl/include/GLES/egl.h b/opengl/include/GLES/egl.h new file mode 100644 index 0000000000..5778e00509 --- /dev/null +++ b/opengl/include/GLES/egl.h @@ -0,0 +1,15 @@ +/* + * Skeleton egl.h to provide compatibility for early GLES 1.0 + * applications. Several early implementations included gl.h + * in egl.h leading applications to include only egl.h + * + * $Revision: 6252 $ on $Date:: 2008-08-06 16:35:08 -0700 #$ + */ + +#ifndef __legacy_egl_h_ +#define __legacy_egl_h_ + +#include <EGL/egl.h> +#include <GLES/gl.h> + +#endif /* __legacy_egl_h_ */ diff --git a/opengl/include/GLES/gl.h b/opengl/include/GLES/gl.h new file mode 100644 index 0000000000..2e8b97107a --- /dev/null +++ b/opengl/include/GLES/gl.h @@ -0,0 +1,769 @@ +#ifndef __gl_h_ +#define __gl_h_ + +/* $Revision: 7172 $ on $Date:: 2009-01-09 11:17:41 -0800 #$ */ + +#include <GLES/glplatform.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +typedef void GLvoid; +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef khronos_int8_t GLbyte; +typedef short GLshort; +typedef int GLint; +typedef int GLsizei; +typedef khronos_uint8_t GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; +typedef khronos_int32_t GLclampx; + +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; + + +/*************************************************************/ + +/* OpenGL ES core versions */ +#define GL_VERSION_ES_CM_1_0 1 +#define GL_VERSION_ES_CL_1_0 1 +#define GL_VERSION_ES_CM_1_1 1 +#define GL_VERSION_ES_CL_1_1 1 + +/* ClearBufferMask */ +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 + +/* Boolean */ +#define GL_FALSE 0 +#define GL_TRUE 1 + +/* BeginMode */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 + +/* AlphaFunction */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 + +/* BlendingFactorDest */ +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 + +/* BlendingFactorSrc */ +/* GL_ZERO */ +/* GL_ONE */ +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +/* GL_SRC_ALPHA */ +/* GL_ONE_MINUS_SRC_ALPHA */ +/* GL_DST_ALPHA */ +/* GL_ONE_MINUS_DST_ALPHA */ + +/* ClipPlaneName */ +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 + +/* ColorMaterialFace */ +/* GL_FRONT_AND_BACK */ + +/* ColorMaterialParameter */ +/* GL_AMBIENT_AND_DIFFUSE */ + +/* ColorPointerType */ +/* GL_UNSIGNED_BYTE */ +/* GL_FLOAT */ +/* GL_FIXED */ + +/* CullFaceMode */ +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 + +/* DepthFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* EnableCap */ +#define GL_FOG 0x0B60 +#define GL_LIGHTING 0x0B50 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_ALPHA_TEST 0x0BC0 +#define GL_BLEND 0x0BE2 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +/* GL_LIGHT0 */ +/* GL_LIGHT1 */ +/* GL_LIGHT2 */ +/* GL_LIGHT3 */ +/* GL_LIGHT4 */ +/* GL_LIGHT5 */ +/* GL_LIGHT6 */ +/* GL_LIGHT7 */ +#define GL_POINT_SMOOTH 0x0B10 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_NORMALIZE 0x0BA1 +#define GL_RESCALE_NORMAL 0x803A +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_COLOR_ARRAY 0x8076 +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 + +/* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_OUT_OF_MEMORY 0x0505 + +/* FogMode */ +/* GL_LINEAR */ +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 + +/* FogParameter */ +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_START 0x0B63 +#define GL_FOG_END 0x0B64 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_COLOR 0x0B66 + +/* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + +/* GetPName */ +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_LINE_WIDTH 0x0B21 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_SHADE_MODEL 0x0B54 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_MATRIX_MODE 0x0BA0 +#define GL_VIEWPORT 0x0BA2 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB + +/* GetTextureParameter */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ + +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 + +/* HintMode */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + +/* HintTarget */ +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_FOG_HINT 0x0C54 +#define GL_GENERATE_MIPMAP_HINT 0x8192 + +/* LightModelParameter */ +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 + +/* LightParameter */ +#define GL_AMBIENT 0x1200 +#define GL_DIFFUSE 0x1201 +#define GL_SPECULAR 0x1202 +#define GL_POSITION 0x1203 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_QUADRATIC_ATTENUATION 0x1209 + +/* DataType */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C + +/* LogicOp */ +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F + +/* MaterialFace */ +/* GL_FRONT_AND_BACK */ + +/* MaterialParameter */ +#define GL_EMISSION 0x1600 +#define GL_SHININESS 0x1601 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +/* GL_AMBIENT */ +/* GL_DIFFUSE */ +/* GL_SPECULAR */ + +/* MatrixMode */ +#define GL_MODELVIEW 0x1700 +#define GL_PROJECTION 0x1701 +#define GL_TEXTURE 0x1702 + +/* NormalPointerType */ +/* GL_BYTE */ +/* GL_SHORT */ +/* GL_FLOAT */ +/* GL_FIXED */ + +/* PixelFormat */ +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A + +/* PixelStoreParameter */ +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 + +/* PixelType */ +/* GL_UNSIGNED_BYTE */ +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 + +/* ShadingModel */ +#define GL_FLAT 0x1D00 +#define GL_SMOOTH 0x1D01 + +/* StencilFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* StencilOp */ +/* GL_ZERO */ +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +/* GL_INVERT */ + +/* StringName */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + +/* TexCoordPointerType */ +/* GL_SHORT */ +/* GL_FLOAT */ +/* GL_FIXED */ +/* GL_BYTE */ + +/* TextureEnvMode */ +#define GL_MODULATE 0x2100 +#define GL_DECAL 0x2101 +/* GL_BLEND */ +#define GL_ADD 0x0104 +/* GL_REPLACE */ + +/* TextureEnvParameter */ +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_ENV_COLOR 0x2201 + +/* TextureEnvTarget */ +#define GL_TEXTURE_ENV 0x2300 + +/* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + +/* TextureMinFilter */ +/* GL_NEAREST */ +/* GL_LINEAR */ +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + +/* TextureParameterName */ +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_GENERATE_MIPMAP 0x8191 + +/* TextureTarget */ +/* GL_TEXTURE_2D */ + +/* TextureUnit */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 + +/* TextureWrapMode */ +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F + +/* VertexPointerType */ +/* GL_SHORT */ +/* GL_FLOAT */ +/* GL_FIXED */ +/* GL_BYTE */ + +/* LightName */ +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 + +/* Buffer Objects */ +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 + +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A + +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 + +/* Texture combine + dot3 */ +#define GL_SUBTRACT 0x84E7 +#define GL_COMBINE 0x8570 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_RGB_SCALE 0x8573 +#define GL_ADD_SIGNED 0x8574 +#define GL_INTERPOLATE 0x8575 +#define GL_CONSTANT 0x8576 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PREVIOUS 0x8578 +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_RGB 0x8592 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND2_ALPHA 0x859A + +#define GL_ALPHA_SCALE 0x0D1C + +#define GL_SRC0_RGB 0x8580 +#define GL_SRC1_RGB 0x8581 +#define GL_SRC2_RGB 0x8582 +#define GL_SRC0_ALPHA 0x8588 +#define GL_SRC1_ALPHA 0x8589 +#define GL_SRC2_ALPHA 0x858A + +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF + +/*------------------------------------------------------------------------* + * required OES extension tokens + *------------------------------------------------------------------------*/ + +/* OES_read_format */ +#ifndef GL_OES_read_format +#define GL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 0x8B9B +#endif + +/* GL_OES_compressed_paletted_texture */ +#ifndef GL_OES_compressed_paletted_texture +#define GL_PALETTE4_RGB8_OES 0x8B90 +#define GL_PALETTE4_RGBA8_OES 0x8B91 +#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 +#define GL_PALETTE4_RGBA4_OES 0x8B93 +#define GL_PALETTE4_RGB5_A1_OES 0x8B94 +#define GL_PALETTE8_RGB8_OES 0x8B95 +#define GL_PALETTE8_RGBA8_OES 0x8B96 +#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 +#define GL_PALETTE8_RGBA4_OES 0x8B98 +#define GL_PALETTE8_RGB5_A1_OES 0x8B99 +#endif + +/* OES_point_size_array */ +#ifndef GL_OES_point_size_array +#define GL_POINT_SIZE_ARRAY_OES 0x8B9C +#define GL_POINT_SIZE_ARRAY_TYPE_OES 0x898A +#define GL_POINT_SIZE_ARRAY_STRIDE_OES 0x898B +#define GL_POINT_SIZE_ARRAY_POINTER_OES 0x898C +#define GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES 0x8B9F +#endif + +/* GL_OES_point_sprite */ +#ifndef GL_OES_point_sprite +#define GL_POINT_SPRITE_OES 0x8861 +#define GL_COORD_REPLACE_OES 0x8862 +#endif + +/*************************************************************/ + +/* Available only in Common profile */ +GL_API void GL_APIENTRY glAlphaFunc (GLenum func, GLclampf ref); +GL_API void GL_APIENTRY glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); +GL_API void GL_APIENTRY glClearDepthf (GLclampf depth); +GL_API void GL_APIENTRY glClipPlanef (GLenum plane, const GLfloat *equation); +GL_API void GL_APIENTRY glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_API void GL_APIENTRY glDepthRangef (GLclampf zNear, GLclampf zFar); +GL_API void GL_APIENTRY glFogf (GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glFogfv (GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glFrustumf (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +GL_API void GL_APIENTRY glGetClipPlanef (GLenum pname, GLfloat eqn[4]); +GL_API void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *params); +GL_API void GL_APIENTRY glGetLightfv (GLenum light, GLenum pname, GLfloat *params); +GL_API void GL_APIENTRY glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params); +GL_API void GL_APIENTRY glGetTexEnvfv (GLenum env, GLenum pname, GLfloat *params); +GL_API void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GL_API void GL_APIENTRY glLightModelf (GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glLightModelfv (GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glLightf (GLenum light, GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glLightfv (GLenum light, GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glLineWidth (GLfloat width); +GL_API void GL_APIENTRY glLoadMatrixf (const GLfloat *m); +GL_API void GL_APIENTRY glMaterialf (GLenum face, GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glMaterialfv (GLenum face, GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glMultMatrixf (const GLfloat *m); +GL_API void GL_APIENTRY glMultiTexCoord4f (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +GL_API void GL_APIENTRY glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz); +GL_API void GL_APIENTRY glOrthof (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +GL_API void GL_APIENTRY glPointParameterf (GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glPointParameterfv (GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glPointSize (GLfloat size); +GL_API void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GL_API void GL_APIENTRY glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +GL_API void GL_APIENTRY glScalef (GLfloat x, GLfloat y, GLfloat z); +GL_API void GL_APIENTRY glTexEnvf (GLenum target, GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glTranslatef (GLfloat x, GLfloat y, GLfloat z); + +/* Available in both Common and Common-Lite profiles */ +GL_API void GL_APIENTRY glActiveTexture (GLenum texture); +GL_API void GL_APIENTRY glAlphaFuncx (GLenum func, GLclampx ref); +GL_API void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_API void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_API void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_API void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); +GL_API void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data); +GL_API void GL_APIENTRY glClear (GLbitfield mask); +GL_API void GL_APIENTRY glClearColorx (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha); +GL_API void GL_APIENTRY glClearDepthx (GLclampx depth); +GL_API void GL_APIENTRY glClearStencil (GLint s); +GL_API void GL_APIENTRY glClientActiveTexture (GLenum texture); +GL_API void GL_APIENTRY glClipPlanex (GLenum plane, const GLfixed *equation); +GL_API void GL_APIENTRY glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +GL_API void GL_APIENTRY glColor4x (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +GL_API void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_API void GL_APIENTRY glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GL_API void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +GL_API void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); +GL_API void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GL_API void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_API void GL_APIENTRY glCullFace (GLenum mode); +GL_API void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); +GL_API void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GL_API void GL_APIENTRY glDepthFunc (GLenum func); +GL_API void GL_APIENTRY glDepthMask (GLboolean flag); +GL_API void GL_APIENTRY glDepthRangex (GLclampx zNear, GLclampx zFar); +GL_API void GL_APIENTRY glDisable (GLenum cap); +GL_API void GL_APIENTRY glDisableClientState (GLenum array); +GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_API void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +GL_API void GL_APIENTRY glEnable (GLenum cap); +GL_API void GL_APIENTRY glEnableClientState (GLenum array); +GL_API void GL_APIENTRY glFinish (void); +GL_API void GL_APIENTRY glFlush (void); +GL_API void GL_APIENTRY glFogx (GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glFogxv (GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glFrontFace (GLenum mode); +GL_API void GL_APIENTRY glFrustumx (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +GL_API void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *params); +GL_API void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_API void GL_APIENTRY glGetClipPlanex (GLenum pname, GLfixed eqn[4]); +GL_API void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); +GL_API void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); +GL_API GLenum GL_APIENTRY glGetError (void); +GL_API void GL_APIENTRY glGetFixedv (GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *params); +GL_API void GL_APIENTRY glGetLightxv (GLenum light, GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glGetMaterialxv (GLenum face, GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glGetPointerv (GLenum pname, void **params); +GL_API const GLubyte * GL_APIENTRY glGetString (GLenum name); +GL_API void GL_APIENTRY glGetTexEnviv (GLenum env, GLenum pname, GLint *params); +GL_API void GL_APIENTRY glGetTexEnvxv (GLenum env, GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GL_API void GL_APIENTRY glGetTexParameterxv (GLenum target, GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glHint (GLenum target, GLenum mode); +GL_API GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); +GL_API GLboolean GL_APIENTRY glIsEnabled (GLenum cap); +GL_API GLboolean GL_APIENTRY glIsTexture (GLuint texture); +GL_API void GL_APIENTRY glLightModelx (GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glLightModelxv (GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glLightx (GLenum light, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glLightxv (GLenum light, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glLineWidthx (GLfixed width); +GL_API void GL_APIENTRY glLoadIdentity (void); +GL_API void GL_APIENTRY glLoadMatrixx (const GLfixed *m); +GL_API void GL_APIENTRY glLogicOp (GLenum opcode); +GL_API void GL_APIENTRY glMaterialx (GLenum face, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glMaterialxv (GLenum face, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glMatrixMode (GLenum mode); +GL_API void GL_APIENTRY glMultMatrixx (const GLfixed *m); +GL_API void GL_APIENTRY glMultiTexCoord4x (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q); +GL_API void GL_APIENTRY glNormal3x (GLfixed nx, GLfixed ny, GLfixed nz); +GL_API void GL_APIENTRY glNormalPointer (GLenum type, GLsizei stride, const GLvoid *pointer); +GL_API void GL_APIENTRY glOrthox (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +GL_API void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +GL_API void GL_APIENTRY glPointParameterx (GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glPointParameterxv (GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glPointSizex (GLfixed size); +GL_API void GL_APIENTRY glPolygonOffsetx (GLfixed factor, GLfixed units); +GL_API void GL_APIENTRY glPopMatrix (void); +GL_API void GL_APIENTRY glPushMatrix (void); +GL_API void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +GL_API void GL_APIENTRY glRotatex (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); +GL_API void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); +GL_API void GL_APIENTRY glSampleCoveragex (GLclampx value, GLboolean invert); +GL_API void GL_APIENTRY glScalex (GLfixed x, GLfixed y, GLfixed z); +GL_API void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GL_API void GL_APIENTRY glShadeModel (GLenum mode); +GL_API void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_API void GL_APIENTRY glStencilMask (GLuint mask); +GL_API void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GL_API void GL_APIENTRY glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GL_API void GL_APIENTRY glTexEnvi (GLenum target, GLenum pname, GLint param); +GL_API void GL_APIENTRY glTexEnvx (GLenum target, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glTexEnviv (GLenum target, GLenum pname, const GLint *params); +GL_API void GL_APIENTRY glTexEnvxv (GLenum target, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GL_API void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GL_API void GL_APIENTRY glTexParameterx (GLenum target, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GL_API void GL_APIENTRY glTexParameterxv (GLenum target, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GL_API void GL_APIENTRY glTranslatex (GLfixed x, GLfixed y, GLfixed z); +GL_API void GL_APIENTRY glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GL_API void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +/*------------------------------------------------------------------------* + * Required OES extension functions + *------------------------------------------------------------------------*/ + +/* GL_OES_read_format */ +#ifndef GL_OES_read_format +#define GL_OES_read_format 1 +#endif + +/* GL_OES_compressed_paletted_texture */ +#ifndef GL_OES_compressed_paletted_texture +#define GL_OES_compressed_paletted_texture 1 +#endif + +/* GL_OES_point_size_array */ +#ifndef GL_OES_point_size_array +#define GL_OES_point_size_array 1 +GL_API void GL_APIENTRY glPointSizePointerOES (GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +/* GL_OES_point_sprite */ +#ifndef GL_OES_point_sprite +#define GL_OES_point_sprite 1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __gl_h_ */ + diff --git a/opengl/include/GLES/glext.h b/opengl/include/GLES/glext.h new file mode 100644 index 0000000000..4c01871aee --- /dev/null +++ b/opengl/include/GLES/glext.h @@ -0,0 +1,622 @@ +#ifndef __glext_h_ +#define __glext_h_ + +/* $Revision: 7172 $ on $Date:: 2009-01-09 11:17:41 -0800 #$ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +#ifndef GL_APIENTRYP +# define GL_APIENTRYP GL_APIENTRY* +#endif + +/*------------------------------------------------------------------------* + * OES extension tokens + *------------------------------------------------------------------------*/ + +/* GL_OES_blend_equation_separate */ +#ifndef GL_OES_blend_equation_separate +/* BLEND_EQUATION_RGB_OES same as BLEND_EQUATION_OES */ +#define GL_BLEND_EQUATION_RGB_OES 0x8009 +#define GL_BLEND_EQUATION_ALPHA_OES 0x883D +#endif + +/* GL_OES_blend_func_separate */ +#ifndef GL_OES_blend_func_separate +#define GL_BLEND_DST_RGB_OES 0x80C8 +#define GL_BLEND_SRC_RGB_OES 0x80C9 +#define GL_BLEND_DST_ALPHA_OES 0x80CA +#define GL_BLEND_SRC_ALPHA_OES 0x80CB +#endif + +/* GL_OES_blend_subtract */ +#ifndef GL_OES_blend_subtract +#define GL_BLEND_EQUATION_OES 0x8009 +#define GL_FUNC_ADD_OES 0x8006 +#define GL_FUNC_SUBTRACT_OES 0x800A +#define GL_FUNC_REVERSE_SUBTRACT_OES 0x800B +#endif + +/* GL_OES_compressed_ETC1_RGB8_texture */ +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_ETC1_RGB8_OES 0x8D64 +#endif + +/* GL_OES_depth24 */ +#ifndef GL_OES_depth24 +#define GL_DEPTH_COMPONENT24_OES 0x81A6 +#endif + +/* GL_OES_depth32 */ +#ifndef GL_OES_depth32 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#endif + +/* GL_OES_draw_texture */ +#ifndef GL_OES_draw_texture +#define GL_TEXTURE_CROP_RECT_OES 0x8B9D +#endif + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +typedef void* GLeglImageOES; +#endif + +/* GL_OES_fixed_point */ +#ifndef GL_OES_fixed_point +#define GL_FIXED_OES 0x140C +#endif + +/* GL_OES_framebuffer_object */ +#ifndef GL_OES_framebuffer_object +#define GL_NONE_OES 0 +#define GL_FRAMEBUFFER_OES 0x8D40 +#define GL_RENDERBUFFER_OES 0x8D41 +#define GL_RGBA4_OES 0x8056 +#define GL_RGB5_A1_OES 0x8057 +#define GL_RGB565_OES 0x8D62 +#define GL_DEPTH_COMPONENT16_OES 0x81A5 +#define GL_RENDERBUFFER_WIDTH_OES 0x8D42 +#define GL_RENDERBUFFER_HEIGHT_OES 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_OES 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE_OES 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE_OES 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE_OES 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE_OES 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE_OES 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE_OES 0x8D55 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_OES 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_OES 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3 +#define GL_COLOR_ATTACHMENT0_OES 0x8CE0 +#define GL_DEPTH_ATTACHMENT_OES 0x8D00 +#define GL_STENCIL_ATTACHMENT_OES 0x8D20 +#define GL_FRAMEBUFFER_COMPLETE_OES 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES 0x8CDA +#define GL_FRAMEBUFFER_UNSUPPORTED_OES 0x8CDD +#define GL_FRAMEBUFFER_BINDING_OES 0x8CA6 +#define GL_RENDERBUFFER_BINDING_OES 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE_OES 0x84E8 +#define GL_INVALID_FRAMEBUFFER_OPERATION_OES 0x0506 +#endif + +/* GL_OES_mapbuffer */ +#ifndef GL_OES_mapbuffer +#define GL_WRITE_ONLY_OES 0x88B9 +#define GL_BUFFER_ACCESS_OES 0x88BB +#define GL_BUFFER_MAPPED_OES 0x88BC +#define GL_BUFFER_MAP_POINTER_OES 0x88BD +#endif + +/* GL_OES_matrix_get */ +#ifndef GL_OES_matrix_get +#define GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES 0x898D +#define GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES 0x898E +#define GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES 0x898F +#endif + +/* GL_OES_matrix_palette */ +#ifndef GL_OES_matrix_palette +#define GL_MAX_VERTEX_UNITS_OES 0x86A4 +#define GL_MAX_PALETTE_MATRICES_OES 0x8842 +#define GL_MATRIX_PALETTE_OES 0x8840 +#define GL_MATRIX_INDEX_ARRAY_OES 0x8844 +#define GL_WEIGHT_ARRAY_OES 0x86AD +#define GL_CURRENT_PALETTE_MATRIX_OES 0x8843 +#define GL_MATRIX_INDEX_ARRAY_SIZE_OES 0x8846 +#define GL_MATRIX_INDEX_ARRAY_TYPE_OES 0x8847 +#define GL_MATRIX_INDEX_ARRAY_STRIDE_OES 0x8848 +#define GL_MATRIX_INDEX_ARRAY_POINTER_OES 0x8849 +#define GL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES 0x8B9E +#define GL_WEIGHT_ARRAY_SIZE_OES 0x86AB +#define GL_WEIGHT_ARRAY_TYPE_OES 0x86A9 +#define GL_WEIGHT_ARRAY_STRIDE_OES 0x86AA +#define GL_WEIGHT_ARRAY_POINTER_OES 0x86AC +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_OES 0x889E +#endif + +/* GL_OES_packed_depth_stencil */ +#ifndef GL_OES_packed_depth_stencil +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif + +/* GL_OES_rgb8_rgba8 */ +#ifndef GL_OES_rgb8_rgba8 +#define GL_RGB8_OES 0x8051 +#define GL_RGBA8_OES 0x8058 +#endif + +/* GL_OES_stencil1 */ +#ifndef GL_OES_stencil1 +#define GL_STENCIL_INDEX1_OES 0x8D46 +#endif + +/* GL_OES_stencil4 */ +#ifndef GL_OES_stencil4 +#define GL_STENCIL_INDEX4_OES 0x8D47 +#endif + +/* GL_OES_stencil8 */ +#ifndef GL_OES_stencil8 +#define GL_STENCIL_INDEX8_OES 0x8D48 +#endif + +/* GL_OES_stencil_wrap */ +#ifndef GL_OES_stencil_wrap +#define GL_INCR_WRAP_OES 0x8507 +#define GL_DECR_WRAP_OES 0x8508 +#endif + +/* GL_OES_texture_cube_map */ +#ifndef GL_OES_texture_cube_map +#define GL_NORMAL_MAP_OES 0x8511 +#define GL_REFLECTION_MAP_OES 0x8512 +#define GL_TEXTURE_CUBE_MAP_OES 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP_OES 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_OES 0x851C +#define GL_TEXTURE_GEN_MODE_OES 0x2500 +#define GL_TEXTURE_GEN_STR_OES 0x8D60 +#endif + +/* GL_OES_texture_mirrored_repeat */ +#ifndef GL_OES_texture_mirrored_repeat +#define GL_MIRRORED_REPEAT_OES 0x8370 +#endif + +/*------------------------------------------------------------------------* + * AMD extension tokens + *------------------------------------------------------------------------*/ + +/* GL_AMD_compressed_3DC_texture */ +#ifndef GL_AMD_compressed_3DC_texture +#define GL_3DC_X_AMD 0x87F9 +#define GL_3DC_XY_AMD 0x87FA +#endif + +/* GL_AMD_compressed_ATC_texture */ +#ifndef GL_AMD_compressed_ATC_texture +#define GL_ATC_RGB_AMD 0x8C92 +#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 +#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE +#endif + +/*------------------------------------------------------------------------* + * EXT extension tokens + *------------------------------------------------------------------------*/ + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +/*------------------------------------------------------------------------* + * OES extension functions + *------------------------------------------------------------------------*/ + +/* GL_OES_blend_equation_separate */ +#ifndef GL_OES_blend_equation_separate +#define GL_OES_blend_equation_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glBlendEquationSeparateOES (GLenum modeRGB, GLenum modeAlpha); +#endif +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEOESPROC) (GLenum modeRGB, GLenum modeAlpha); +#endif + +/* GL_OES_blend_func_separate */ +#ifndef GL_OES_blend_func_separate +#define GL_OES_blend_func_separate 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glBlendFuncSeparateOES (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +#endif +typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEOESPROC) (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +#endif + +/* GL_OES_blend_subtract */ +#ifndef GL_OES_blend_subtract +#define GL_OES_blend_subtract 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glBlendEquationOES (GLenum mode); +#endif +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONOESPROC) (GLenum mode); +#endif + +/* GL_OES_byte_coordinates */ +#ifndef GL_OES_byte_coordinates +#define GL_OES_byte_coordinates 1 +#endif + +/* GL_OES_compressed_ETC1_RGB8_texture */ +#ifndef GL_OES_compressed_ETC1_RGB8_texture +#define GL_OES_compressed_ETC1_RGB8_texture 1 +#endif + +/* GL_OES_depth24 */ +#ifndef GL_OES_depth24 +#define GL_OES_depth24 1 +#endif + +/* GL_OES_depth32 */ +#ifndef GL_OES_depth32 +#define GL_OES_depth32 1 +#endif + +/* GL_OES_draw_texture */ +#ifndef GL_OES_draw_texture +#define GL_OES_draw_texture 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glDrawTexsOES (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height); +GL_API void GL_APIENTRY glDrawTexiOES (GLint x, GLint y, GLint z, GLint width, GLint height); +GL_API void GL_APIENTRY glDrawTexxOES (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height); +GL_API void GL_APIENTRY glDrawTexsvOES (const GLshort *coords); +GL_API void GL_APIENTRY glDrawTexivOES (const GLint *coords); +GL_API void GL_APIENTRY glDrawTexxvOES (const GLfixed *coords); +GL_API void GL_APIENTRY glDrawTexfOES (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); +GL_API void GL_APIENTRY glDrawTexfvOES (const GLfloat *coords); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWTEXSOESPROC) (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height); +typedef void (GL_APIENTRYP PFNGLDRAWTEXIOESPROC) (GLint x, GLint y, GLint z, GLint width, GLint height); +typedef void (GL_APIENTRYP PFNGLDRAWTEXXOESPROC) (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height); +typedef void (GL_APIENTRYP PFNGLDRAWTEXSVOESPROC) (const GLshort *coords); +typedef void (GL_APIENTRYP PFNGLDRAWTEXIVOESPROC) (const GLint *coords); +typedef void (GL_APIENTRYP PFNGLDRAWTEXXVOESPROC) (const GLfixed *coords); +typedef void (GL_APIENTRYP PFNGLDRAWTEXFOESPROC) (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); +typedef void (GL_APIENTRYP PFNGLDRAWTEXFVOESPROC) (const GLfloat *coords); +#endif + +/* GL_OES_EGL_image */ +#ifndef GL_OES_EGL_image +#define GL_OES_EGL_image 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image); +GL_API void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image); +#endif +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); +typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); +#endif + +/* GL_OES_element_index_uint */ +#ifndef GL_OES_element_index_uint +#define GL_OES_element_index_uint 1 +#endif + +/* GL_OES_extended_matrix_palette */ +#ifndef GL_OES_extended_matrix_palette +#define GL_OES_extended_matrix_palette 1 +#endif + +/* GL_OES_fbo_render_mipmap */ +#ifndef GL_OES_fbo_render_mipmap +#define GL_OES_fbo_render_mipmap 1 +#endif + +/* GL_OES_fixed_point */ +#ifndef GL_OES_fixed_point +#define GL_OES_fixed_point 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glAlphaFuncxOES (GLenum func, GLclampx ref); +GL_API void GL_APIENTRY glClearColorxOES (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha); +GL_API void GL_APIENTRY glClearDepthxOES (GLclampx depth); +GL_API void GL_APIENTRY glClipPlanexOES (GLenum plane, const GLfixed *equation); +GL_API void GL_APIENTRY glColor4xOES (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +GL_API void GL_APIENTRY glDepthRangexOES (GLclampx zNear, GLclampx zFar); +GL_API void GL_APIENTRY glFogxOES (GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glFogxvOES (GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glFrustumxOES (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +GL_API void GL_APIENTRY glGetClipPlanexOES (GLenum pname, GLfixed eqn[4]); +GL_API void GL_APIENTRY glGetFixedvOES (GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glGetLightxvOES (GLenum light, GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glGetMaterialxvOES (GLenum face, GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glGetTexEnvxvOES (GLenum env, GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glGetTexParameterxvOES (GLenum target, GLenum pname, GLfixed *params); +GL_API void GL_APIENTRY glLightModelxOES (GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glLightModelxvOES (GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glLightxOES (GLenum light, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glLightxvOES (GLenum light, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glLineWidthxOES (GLfixed width); +GL_API void GL_APIENTRY glLoadMatrixxOES (const GLfixed *m); +GL_API void GL_APIENTRY glMaterialxOES (GLenum face, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glMaterialxvOES (GLenum face, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glMultMatrixxOES (const GLfixed *m); +GL_API void GL_APIENTRY glMultiTexCoord4xOES (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q); +GL_API void GL_APIENTRY glNormal3xOES (GLfixed nx, GLfixed ny, GLfixed nz); +GL_API void GL_APIENTRY glOrthoxOES (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +GL_API void GL_APIENTRY glPointParameterxOES (GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glPointSizexOES (GLfixed size); +GL_API void GL_APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units); +GL_API void GL_APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); +GL_API void GL_APIENTRY glSampleCoveragexOES (GLclampx value, GLboolean invert); +GL_API void GL_APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z); +GL_API void GL_APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glTexParameterxOES (GLenum target, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glTexParameterxvOES (GLenum target, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glTranslatexOES (GLfixed x, GLfixed y, GLfixed z); +#endif +typedef void (GL_APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLclampx ref); +typedef void (GL_APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLclampx red, GLclampx green, GLclampx blue, GLclampx alpha); +typedef void (GL_APIENTRYP PFNGLCLEARDEPTHXOESPROC) (GLclampx depth); +typedef void (GL_APIENTRYP PFNGLCLIPPLANEXOESPROC) (GLenum plane, const GLfixed *equation); +typedef void (GL_APIENTRYP PFNGLCOLOR4XOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); +typedef void (GL_APIENTRYP PFNGLDEPTHRANGEXOESPROC) (GLclampx zNear, GLclampx zFar); +typedef void (GL_APIENTRYP PFNGLFOGXOESPROC) (GLenum pname, GLfixed param); +typedef void (GL_APIENTRYP PFNGLFOGXVOESPROC) (GLenum pname, const GLfixed *params); +typedef void (GL_APIENTRYP PFNGLFRUSTUMXOESPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +typedef void (GL_APIENTRYP PFNGLGETCLIPPLANEXOESPROC) (GLenum pname, GLfixed eqn[4]); +typedef void (GL_APIENTRYP PFNGLGETFIXEDVOESPROC) (GLenum pname, GLfixed *params); +typedef void (GL_APIENTRYP PFNGLGETLIGHTXVOESPROC) (GLenum light, GLenum pname, GLfixed *params); +typedef void (GL_APIENTRYP PFNGLGETMATERIALXVOESPROC) (GLenum face, GLenum pname, GLfixed *params); +typedef void (GL_APIENTRYP PFNGLGETTEXENVXVOESPROC) (GLenum env, GLenum pname, GLfixed *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, GLfixed *params); +typedef void (GL_APIENTRYP PFNGLLIGHTMODELXOESPROC) (GLenum pname, GLfixed param); +typedef void (GL_APIENTRYP PFNGLLIGHTMODELXVOESPROC) (GLenum pname, const GLfixed *params); +typedef void (GL_APIENTRYP PFNGLLIGHTXOESPROC) (GLenum light, GLenum pname, GLfixed param); +typedef void (GL_APIENTRYP PFNGLLIGHTXVOESPROC) (GLenum light, GLenum pname, const GLfixed *params); +typedef void (GL_APIENTRYP PFNGLLINEWIDTHXOESPROC) (GLfixed width); +typedef void (GL_APIENTRYP PFNGLLOADMATRIXXOESPROC) (const GLfixed *m); +typedef void (GL_APIENTRYP PFNGLMATERIALXOESPROC) (GLenum face, GLenum pname, GLfixed param); +typedef void (GL_APIENTRYP PFNGLMATERIALXVOESPROC) (GLenum face, GLenum pname, const GLfixed *params); +typedef void (GL_APIENTRYP PFNGLMULTMATRIXXOESPROC) (const GLfixed *m); +typedef void (GL_APIENTRYP PFNGLMULTITEXCOORD4XOESPROC) (GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q); +typedef void (GL_APIENTRYP PFNGLNORMAL3XOESPROC) (GLfixed nx, GLfixed ny, GLfixed nz); +typedef void (GL_APIENTRYP PFNGLORTHOXOESPROC) (GLfixed left, GLfixed right, GLfixed bottom, GLfixed top, GLfixed zNear, GLfixed zFar); +typedef void (GL_APIENTRYP PFNGLPOINTPARAMETERXOESPROC) (GLenum pname, GLfixed param); +typedef void (GL_APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfixed *params); +typedef void (GL_APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size); +typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units); +typedef void (GL_APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); +typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEXOESPROC) (GLclampx value, GLboolean invert); +typedef void (GL_APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z); +typedef void (GL_APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param); +typedef void (GL_APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERXOESPROC) (GLenum target, GLenum pname, GLfixed param); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); +typedef void (GL_APIENTRYP PFNGLTRANSLATEXOESPROC) (GLfixed x, GLfixed y, GLfixed z); +#endif + +/* GL_OES_framebuffer_object */ +#ifndef GL_OES_framebuffer_object +#define GL_OES_framebuffer_object 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API GLboolean GL_APIENTRY glIsRenderbufferOES (GLuint renderbuffer); +GL_API void GL_APIENTRY glBindRenderbufferOES (GLenum target, GLuint renderbuffer); +GL_API void GL_APIENTRY glDeleteRenderbuffersOES (GLsizei n, const GLuint* renderbuffers); +GL_API void GL_APIENTRY glGenRenderbuffersOES (GLsizei n, GLuint* renderbuffers); +GL_API void GL_APIENTRY glRenderbufferStorageOES (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GL_API void GL_APIENTRY glGetRenderbufferParameterivOES (GLenum target, GLenum pname, GLint* params); +GL_API GLboolean GL_APIENTRY glIsFramebufferOES (GLuint framebuffer); +GL_API void GL_APIENTRY glBindFramebufferOES (GLenum target, GLuint framebuffer); +GL_API void GL_APIENTRY glDeleteFramebuffersOES (GLsizei n, const GLuint* framebuffers); +GL_API void GL_APIENTRY glGenFramebuffersOES (GLsizei n, GLuint* framebuffers); +GL_API GLenum GL_APIENTRY glCheckFramebufferStatusOES (GLenum target); +GL_API void GL_APIENTRY glFramebufferRenderbufferOES (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GL_API void GL_APIENTRY glFramebufferTexture2DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GL_API void GL_APIENTRY glGetFramebufferAttachmentParameterivOES (GLenum target, GLenum attachment, GLenum pname, GLint* params); +GL_API void GL_APIENTRY glGenerateMipmapOES (GLenum target); +#endif +typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFEROESPROC) (GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFEROESPROC) (GLenum target, GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSOESPROC) (GLsizei n, const GLuint* renderbuffers); +typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSOESPROC) (GLsizei n, GLuint* renderbuffers); +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVOESPROC) (GLenum target, GLenum pname, GLint* params); +typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFEROESPROC) (GLuint framebuffer); +typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFEROESPROC) (GLenum target, GLuint framebuffer); +typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSOESPROC) (GLsizei n, const GLuint* framebuffers); +typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSOESPROC) (GLsizei n, GLuint* framebuffers); +typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSOESPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFEROESPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVOESPROC) (GLenum target, GLenum attachment, GLenum pname, GLint* params); +typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPOESPROC) (GLenum target); +#endif + +/* GL_OES_mapbuffer */ +#ifndef GL_OES_mapbuffer +#define GL_OES_mapbuffer 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void* GL_APIENTRY glMapBufferOES (GLenum target, GLenum access); +GL_API GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target); +GL_API void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void** params); +#endif +typedef void* (GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access); +typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void** params); +#endif + +/* GL_OES_matrix_get */ +#ifndef GL_OES_matrix_get +#define GL_OES_matrix_get 1 +#endif + +/* GL_OES_matrix_palette */ +#ifndef GL_OES_matrix_palette +#define GL_OES_matrix_palette 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glCurrentPaletteMatrixOES (GLuint matrixpaletteindex); +GL_API void GL_APIENTRY glLoadPaletteFromModelViewMatrixOES (void); +GL_API void GL_APIENTRY glMatrixIndexPointerOES (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +GL_API void GL_APIENTRY glWeightPointerOES (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif +typedef void (GL_APIENTRYP PFNGLCURRENTPALETTEMATRIXOESPROC) (GLuint matrixpaletteindex); +typedef void (GL_APIENTRYP PFNGLLOADPALETTEFROMMODELVIEWMATRIXOESPROC) (void); +typedef void (GL_APIENTRYP PFNGLMATRIXINDEXPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +typedef void (GL_APIENTRYP PFNGLWEIGHTPOINTEROESPROC) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +#endif + +/* GL_OES_packed_depth_stencil */ +#ifndef GL_OES_packed_depth_stencil +#define GL_OES_packed_depth_stencil 1 +#endif + +/* GL_OES_query_matrix */ +#ifndef GL_OES_query_matrix +#define GL_OES_query_matrix 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API GLbitfield GL_APIENTRY glQueryMatrixxOES (GLfixed mantissa[16], GLint exponent[16]); +#endif +typedef GLbitfield (GL_APIENTRYP PFNGLQUERYMATRIXXOESPROC) (GLfixed mantissa[16], GLint exponent[16]); +#endif + +/* GL_OES_rgb8_rgba8 */ +#ifndef GL_OES_rgb8_rgba8 +#define GL_OES_rgb8_rgba8 1 +#endif + +/* GL_OES_single_precision */ +#ifndef GL_OES_single_precision +#define GL_OES_single_precision 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glDepthRangefOES (GLclampf zNear, GLclampf zFar); +GL_API void GL_APIENTRY glFrustumfOES (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +GL_API void GL_APIENTRY glOrthofOES (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +GL_API void GL_APIENTRY glClipPlanefOES (GLenum plane, const GLfloat *equation); +GL_API void GL_APIENTRY glGetClipPlanefOES (GLenum pname, GLfloat eqn[4]); +GL_API void GL_APIENTRY glClearDepthfOES (GLclampf depth); +#endif +typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFOESPROC) (GLclampf zNear, GLclampf zFar); +typedef void (GL_APIENTRYP PFNGLFRUSTUMFOESPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +typedef void (GL_APIENTRYP PFNGLORTHOFOESPROC) (GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +typedef void (GL_APIENTRYP PFNGLCLIPPLANEFOESPROC) (GLenum plane, const GLfloat *equation); +typedef void (GL_APIENTRYP PFNGLGETCLIPPLANEFOESPROC) (GLenum pname, GLfloat eqn[4]); +typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFOESPROC) (GLclampf depth); +#endif + +/* GL_OES_stencil1 */ +#ifndef GL_OES_stencil1 +#define GL_OES_stencil1 1 +#endif + +/* GL_OES_stencil4 */ +#ifndef GL_OES_stencil4 +#define GL_OES_stencil4 1 +#endif + +/* GL_OES_stencil8 */ +#ifndef GL_OES_stencil8 +#define GL_OES_stencil8 1 +#endif + +/* GL_OES_stencil_wrap */ +#ifndef GL_OES_stencil_wrap +#define GL_OES_stencil_wrap 1 +#endif + +/* GL_OES_texture_cube_map */ +#ifndef GL_OES_texture_cube_map +#define GL_OES_texture_cube_map 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_API void GL_APIENTRY glTexGenfOES (GLenum coord, GLenum pname, GLfloat param); +GL_API void GL_APIENTRY glTexGenfvOES (GLenum coord, GLenum pname, const GLfloat *params); +GL_API void GL_APIENTRY glTexGeniOES (GLenum coord, GLenum pname, GLint param); +GL_API void GL_APIENTRY glTexGenivOES (GLenum coord, GLenum pname, const GLint *params); +GL_API void GL_APIENTRY glTexGenxOES (GLenum coord, GLenum pname, GLfixed param); +GL_API void GL_APIENTRY glTexGenxvOES (GLenum coord, GLenum pname, const GLfixed *params); +GL_API void GL_APIENTRY glGetTexGenfvOES (GLenum coord, GLenum pname, GLfloat *params); +GL_API void GL_APIENTRY glGetTexGenivOES (GLenum coord, GLenum pname, GLint *params); +GL_API void GL_APIENTRY glGetTexGenxvOES (GLenum coord, GLenum pname, GLfixed *params); +#endif +typedef void (GL_APIENTRYP PFNGLTEXGENFOESPROC) (GLenum coord, GLenum pname, GLfloat param); +typedef void (GL_APIENTRYP PFNGLTEXGENFVOESPROC) (GLenum coord, GLenum pname, const GLfloat *params); +typedef void (GL_APIENTRYP PFNGLTEXGENIOESPROC) (GLenum coord, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLTEXGENIVOESPROC) (GLenum coord, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP PFNGLTEXGENXOESPROC) (GLenum coord, GLenum pname, GLfixed param); +typedef void (GL_APIENTRYP PFNGLTEXGENXVOESPROC) (GLenum coord, GLenum pname, const GLfixed *params); +typedef void (GL_APIENTRYP PFNGLGETTEXGENFVOESPROC) (GLenum coord, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETTEXGENIVOESPROC) (GLenum coord, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXGENXVOESPROC) (GLenum coord, GLenum pname, GLfixed *params); +#endif + +/* GL_OES_texture_env_crossbar */ +#ifndef GL_OES_texture_env_crossbar +#define GL_OES_texture_env_crossbar 1 +#endif + +/* GL_OES_texture_mirrored_repeat */ +#ifndef GL_OES_texture_mirrored_repeat +#define GL_OES_texture_mirrored_repeat 1 +#endif + +/*------------------------------------------------------------------------* + * AMD extension functions + *------------------------------------------------------------------------*/ + +/* GL_AMD_compressed_3DC_texture */ +#ifndef GL_AMD_compressed_3DC_texture +#define GL_AMD_compressed_3DC_texture 1 +#endif + +/* GL_AMD_compressed_ATC_texture */ +#ifndef GL_AMD_compressed_ATC_texture +#define GL_AMD_compressed_ATC_texture 1 +#endif + +/*------------------------------------------------------------------------* + * EXT extension functions + *------------------------------------------------------------------------*/ + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_EXT_texture_filter_anisotropic 1 +#endif + +/*------------------------------------------------------------------------* + * dalvik extension functions + *------------------------------------------------------------------------*/ +#ifdef ANDROID +void glColorPointerBounds(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr, GLsizei count); +void glNormalPointerBounds(GLenum type, GLsizei stride, + const GLvoid *pointer, GLsizei count); +void glTexCoordPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count); +void glVertexPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* __glext_h_ */ + diff --git a/opengl/include/GLES/glplatform.h b/opengl/include/GLES/glplatform.h new file mode 100644 index 0000000000..0924caeaff --- /dev/null +++ b/opengl/include/GLES/glplatform.h @@ -0,0 +1,39 @@ +#ifndef __glplatform_h_ +#define __glplatform_h_ + +/* $Revision: 7172 $ on $Date:: 2009-01-09 11:17:41 -0800 #$ */ + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/* Platform-specific types and definitions for OpenGL ES 1.X gl.h + * Last modified on 2008/12/19 + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "OpenGL-ES" component "Registry". + */ + +#include <KHR/khrplatform.h> + +#ifndef GL_API +#define GL_API KHRONOS_APICALL +#endif + +#if defined(ANDROID) + +#define GL_APIENTRY KHRONOS_APIENTRY + +// XXX: this should probably not be here +#define GL_DIRECT_TEXTURE_2D_QUALCOMM 0x7E80 + +// XXX: not sure how this is intended to be used +#define GL_GLEXT_PROTOTYPES + +#endif + +#endif /* __glplatform_h_ */ diff --git a/opengl/include/KHR/khrplatform.h b/opengl/include/KHR/khrplatform.h new file mode 100644 index 0000000000..4cc27c52da --- /dev/null +++ b/opengl/include/KHR/khrplatform.h @@ -0,0 +1,241 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2009 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Platform-specific types and definitions. + * $Revision: 7244 $ on $Date: 2009-01-20 17:06:59 -0800 (Tue, 20 Jan 2009) $ + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by sending them to the public Khronos Bugzilla + * (http://khronos.org/bugzilla) by filing a bug against product + * "Khronos (general)" component "Registry". + * + * A predefined template which fills in some of the bug fields can be + * reached using http://tinyurl.com/khrplatform-h-bugreport, but you + * must create a Bugzilla login first. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system. + * http://www.khronos.org/registry/implementers_guide.pdf + * + * + * This file should be included as + * #include <KHR/khrplatform.h> + * by the Khronos API header file that uses its types and defines. + * + * The types in this file should only be used to define API-specific types. + * Types defined in this file: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * + * Macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * These may be used in function prototypes as: + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(_WIN32) && !defined(__SCITECH_SNAP__) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using <stdint.h> + */ +#include <stdint.h> +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using <inttypes.h> + */ +#include <inttypes.h> +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include <stdint.h> +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + + +#endif /* __khrplatform_h_ */ diff --git a/opengl/libGLES_CM/Android.mk b/opengl/libGLES_CM/Android.mk deleted file mode 100644 index e350e0225c..0000000000 --- a/opengl/libGLES_CM/Android.mk +++ /dev/null @@ -1,24 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -# -# Build the wrapper OpenGL ES library -# - -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= gl_wrapper.cpp.arm gl_logger.cpp - -LOCAL_SHARED_LIBRARIES += libcutils libutils libui -LOCAL_LDLIBS := -lpthread -ldl -LOCAL_MODULE:= libGLES_CM - -# needed on sim build because of weird logging issues -ifeq ($(TARGET_SIMULATOR),true) -else - LOCAL_SHARED_LIBRARIES += libdl - # we need to access the Bionic private header <bionic_tls.h> - LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private -endif - -include $(BUILD_SHARED_LIBRARY) - diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp index 3e8dca958d..5b90bf03fd 100644 --- a/opengl/libagl/egl.cpp +++ b/opengl/libagl/egl.cpp @@ -33,7 +33,10 @@ #include <utils/threads.h> -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES/gl.h> +#include <GLES/glext.h> #include <pixelflinger/format.h> #include <pixelflinger/pixelflinger.h> @@ -149,7 +152,6 @@ struct egl_surface_t virtual EGLint getRefreshRate() const; virtual EGLint getSwapBehavior() const; virtual EGLBoolean swapBuffers(); - virtual EGLBoolean swapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); protected: GGLSurface depth; }; @@ -171,10 +173,6 @@ egl_surface_t::~egl_surface_t() EGLBoolean egl_surface_t::swapBuffers() { return EGL_FALSE; } -EGLBoolean egl_surface_t::swapRectangle( - EGLint l, EGLint t, EGLint w, EGLint h) { - return EGL_FALSE; -} EGLint egl_surface_t::getHorizontalResolution() const { return (0 * EGL_DISPLAY_SCALING) * (1.0f / 25.4f); } @@ -201,7 +199,6 @@ struct egl_window_surface_t : public egl_surface_t virtual bool isValid() const { return nativeWindow->magic == 0x600913; } virtual EGLBoolean swapBuffers(); - virtual EGLBoolean swapRectangle(EGLint l, EGLint t, EGLint w, EGLint h); virtual EGLBoolean bindDrawSurface(ogles_context_t* gl); virtual EGLBoolean bindReadSurface(ogles_context_t* gl); virtual EGLint getWidth() const { return nativeWindow->width; } @@ -243,7 +240,6 @@ EGLBoolean egl_window_surface_t::swapBuffers() if (flags & EGL_NATIVES_FLAG_SIZE_CHANGED) { // TODO: we probably should reset the swap rect here // if the window size has changed - // window->setSwapRectangle(Rect(info.w, info.h)); if (depth.data) { free(depth.data); depth.width = nativeWindow->width; @@ -259,12 +255,6 @@ EGLBoolean egl_window_surface_t::swapBuffers() return EGL_TRUE; } -EGLBoolean egl_window_surface_t::swapRectangle( - EGLint l, EGLint t, EGLint w, EGLint h) -{ - nativeWindow->setSwapRectangle(nativeWindow, l, t, w, h); - return EGL_TRUE; -} EGLBoolean egl_window_surface_t::bindDrawSurface(ogles_context_t* gl) { GGLSurface buffer; @@ -473,24 +463,21 @@ struct config_management_t { // ---------------------------------------------------------------------------- +#define VERSION_MAJOR 1 +#define VERSION_MINOR 2 static char const * const gVendorString = "Google Inc."; static char const * const gVersionString = "1.2 Android Driver"; static char const * const gClientApiString = "OpenGL ES"; -static char const * const gExtensionsString = - "EGL_ANDROID_swap_rectangle" " " - "EGL_ANDROID_copy_front_to_back" " " - "EGL_ANDROID_get_render_buffer_address" - ; +static char const * const gExtensionsString = ""; // ---------------------------------------------------------------------------- struct extention_map_t { const char * const name; - void (*address)(void); + __eglMustCastToProperFunctionPointerType address; }; static const extention_map_t gExtentionMap[] = { - { "eglSwapRectangleANDROID", (void(*)())&eglSwapRectangleANDROID }, { "glDrawTexsOES", (void(*)())&glDrawTexsOES }, { "glDrawTexiOES", (void(*)())&glDrawTexiOES }, { "glDrawTexfOES", (void(*)())&glDrawTexfOES }, @@ -1017,8 +1004,8 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) } if (res == EGL_TRUE) { - if (major != NULL) *major = 1; - if (minor != NULL) *minor = 2; + if (major != NULL) *major = VERSION_MAJOR; + if (minor != NULL) *minor = VERSION_MINOR; } return res; } @@ -1554,15 +1541,3 @@ void (*eglGetProcAddress (const char *procname))() } return NULL; } - -EGLBoolean eglSwapRectangleANDROID( - EGLDisplay dpy, EGLSurface draw, - EGLint l, EGLint t, EGLint w, EGLint h) -{ - if (egl_display_t::is_valid(dpy) == EGL_FALSE) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - egl_surface_t* surface = (egl_surface_t*)draw; - if (surface->dpy != dpy) - return setError(EGL_BAD_DISPLAY, EGL_FALSE); - return surface->swapRectangle(l, t, w, h); -} diff --git a/opengl/libagl/state.cpp b/opengl/libagl/state.cpp index c2f9f12356..5cbabea1f8 100644 --- a/opengl/libagl/state.cpp +++ b/opengl/libagl/state.cpp @@ -403,12 +403,6 @@ void glGetIntegerv(GLenum pname, GLint *params) case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: params[0] = GL_UNSIGNED_SHORT_5_6_5; break; - case GL_MAX_ELEMENTS_INDICES: - params[0] = 65536; - break; - case GL_MAX_ELEMENTS_VERTICES: - params[0] = 0x7FFFFFFF; - break; case GL_MAX_LIGHTS: params[0] = OGLES_MAX_LIGHTS; break; diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp index 6b2640a720..b6f534b7ea 100644 --- a/opengl/libagl/texture.cpp +++ b/opengl/libagl/texture.cpp @@ -526,7 +526,7 @@ void generateMipmap(ogles_context_t* c, GLint level) static void texParameterx( GLenum target, GLenum pname, GLfixed param, ogles_context_t* c) { - if (target != GGL_TEXTURE_2D) { + if (target != GL_TEXTURE_2D) { ogles_error(c, GL_INVALID_ENUM); return; } @@ -534,8 +534,7 @@ static void texParameterx( EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; switch (pname) { case GL_TEXTURE_WRAP_S: - if ((param == GL_CLAMP) || - (param == GL_REPEAT) || + if ((param == GL_REPEAT) || (param == GL_CLAMP_TO_EDGE)) { textureObject->wraps = param; } else { @@ -543,9 +542,8 @@ static void texParameterx( } break; case GL_TEXTURE_WRAP_T: - if ((param == GGL_CLAMP) || - (param == GGL_REPEAT) || - (param == GGL_CLAMP_TO_EDGE)) { + if ((param == GL_REPEAT) || + (param == GL_CLAMP_TO_EDGE)) { textureObject->wrapt = param; } else { goto invalid_enum; @@ -1006,7 +1004,7 @@ void glCompressedTexImage2D( void glTexImage2D( - GLenum target, GLint level, GLenum internalformat, + GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk new file mode 100644 index 0000000000..2ecc7768ca --- /dev/null +++ b/opengl/libs/Android.mk @@ -0,0 +1,53 @@ +LOCAL_PATH:= $(call my-dir) + +# +# Build META EGL library +# + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + EGL/egl.cpp \ + EGL/gpu.cpp \ +# + +LOCAL_SHARED_LIBRARIES += libcutils libutils libui +LOCAL_LDLIBS := -lpthread -ldl +LOCAL_MODULE:= libEGL + +# needed on sim build because of weird logging issues +ifeq ($(TARGET_SIMULATOR),true) +else + LOCAL_SHARED_LIBRARIES += libdl + # we need to access the Bionic private header <bionic_tls.h> + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private +endif + +include $(BUILD_SHARED_LIBRARY) + + + +# +# Build the wrapper OpenGL ES library +# + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + GLES_CM/gl.cpp.arm \ + GLES_CM/gl_logger.cpp \ +# + +LOCAL_SHARED_LIBRARIES += libcutils libutils libui libEGL +LOCAL_LDLIBS := -lpthread -ldl +LOCAL_MODULE:= libGLESv1_CM + +# needed on sim build because of weird logging issues +ifeq ($(TARGET_SIMULATOR),true) +else + LOCAL_SHARED_LIBRARIES += libdl + # we need to access the Bionic private header <bionic_tls.h> + LOCAL_CFLAGS += -I$(LOCAL_PATH)/../../../../bionic/libc/private +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/opengl/libGLES_CM/gl_wrapper.cpp b/opengl/libs/EGL/egl.cpp index 319753570d..687c8bc1f7 100644 --- a/opengl/libGLES_CM/gl_wrapper.cpp +++ b/opengl/libs/EGL/egl.cpp @@ -27,31 +27,22 @@ #include <linux/android_pmem.h> #endif -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES/gl.h> +#include <GLES/glext.h> #include <cutils/log.h> #include <cutils/atomic.h> #include <cutils/properties.h> #include <cutils/memory.h> -#include <utils/IMemory.h> -#include <utils/KeyedVector.h> -#include <utils/threads.h> -#include <utils/IServiceManager.h> -#include <utils/IPCThreadState.h> -#include <utils/Parcel.h> +#include <utils/RefBase.h> -#include <ui/EGLDisplaySurface.h> -#include <ui/ISurfaceComposer.h> +#include "hooks.h" +#include "egl_impl.h" -#include "gl_logger.h" -#undef NELEM - -#define GL_LOGGER 0 -#define USE_SLOW_BINDING 0 -#define NELEM(x) (sizeof(x)/sizeof(*(x))) -#define MAX_NUMBER_OF_GL_EXTENSIONS 32 #define MAKE_CONFIG(_impl, _index) ((EGLConfig)(((_impl)<<24) | (_index))) #define setError(_e, _r) setErrorEtc(__FUNCTION__, __LINE__, _e, _r) @@ -59,26 +50,12 @@ namespace android { // ---------------------------------------------------------------------------- -// EGLDisplay are global, not attached to a given thread -static const unsigned int NUM_DISPLAYS = 1; -static const unsigned int IMPL_HARDWARE = 0; -static const unsigned int IMPL_SOFTWARE = 1; -static const unsigned int IMPL_HARDWARE_CONTEXT_LOST = 2; -static const unsigned int IMPL_SOFTWARE_CONTEXT_LOST = 3; -static const unsigned int IMPL_NO_CONTEXT = 4; - -// ---------------------------------------------------------------------------- - -struct gl_hooks_t; - -struct egl_connection_t -{ - void volatile * dso; - gl_hooks_t * hooks; - EGLint major; - EGLint minor; - int unavailable; -}; +#define VERSION_MAJOR 1 +#define VERSION_MINOR 4 +static char const * const gVendorString = "Android"; +static char const * const gVersionString = "1.31 Android META-EGL"; +static char const * const gClientApiString = "OpenGL ES"; +static char const * const gExtensionString = ""; template <int MAGIC> struct egl_object_t @@ -103,7 +80,6 @@ struct egl_display_t : public egl_object_t<'_dpy'> char const * version; char const * clientApi; char const * extensions; - char const * extensions_config; }; strings_t queryString[2]; }; @@ -152,82 +128,45 @@ struct tls_t EGLContext ctx; }; +static void gl_unimplemented() { + LOGE("called unimplemented OpenGL ES API"); +} +// ---------------------------------------------------------------------------- // GL / EGL hooks +// ---------------------------------------------------------------------------- -typedef void(*proc_t)(); - -struct gl_hooks_t { - struct gl_t { - #define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); - #include "gl_entries.cpp" - #undef GL_ENTRY - } gl; - struct egl_t { - #define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); - #include "egl_entries.cpp" - #undef EGL_ENTRY - } egl; - struct gl_ext_t { - void (*extensions[MAX_NUMBER_OF_GL_EXTENSIONS])(void); - } ext; -}; +#undef GL_ENTRY +#undef EGL_ENTRY +#define GL_ENTRY(_r, _api, ...) #_api, +#define EGL_ENTRY(_r, _api, ...) #_api, static char const * const gl_names[] = { - #define GL_ENTRY(_r, _api, ...) #_api, - #include "gl_entries.cpp" - #undef GL_ENTRY + #include "gl_entries.in" NULL }; static char const * const egl_names[] = { - #define EGL_ENTRY(_r, _api, ...) #_api, - #include "egl_entries.cpp" - #undef EGL_ENTRY + #include "egl_entries.in" NULL }; -static void gl_unimplemented() { - LOGE("called unimplemented OpenGL ES API"); -} +#undef GL_ENTRY +#undef EGL_ENTRY // ---------------------------------------------------------------------------- -static egl_connection_t gEGLImpl[2]; +egl_connection_t gEGLImpl[2]; static egl_display_t gDisplay[NUM_DISPLAYS]; -static gl_hooks_t gHooks[5]; static pthread_mutex_t gThreadLocalStorageKeyMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_key_t gEGLThreadLocalStorageKey = -1; // ---------------------------------------------------------------------------- -#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && !GL_LOGGER +gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS]; +pthread_key_t gGLWrapperKey = -1; -/* special private C library header */ -#include <bionic_tls.h> -// We have a dedicated TLS slot in bionic -static inline void setGlThreadSpecific(gl_hooks_t const *value) { - ((uint32_t *)__get_tls())[TLS_SLOT_OPENGL_API] = (uint32_t)value; -} -static gl_hooks_t const* getGlThreadSpecific() { - gl_hooks_t const* hooks = (gl_hooks_t const *)(((unsigned const *)__get_tls())[TLS_SLOT_OPENGL_API]); - if (hooks) return hooks; - return &gHooks[IMPL_NO_CONTEXT]; -} - -#else - -static pthread_key_t gGLWrapperKey = -1; -static inline void setGlThreadSpecific(gl_hooks_t const *value) { - pthread_setspecific(gGLWrapperKey, value); -} -static gl_hooks_t const* getGlThreadSpecific() { - gl_hooks_t const* hooks = static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey)); - if (hooks) return hooks; - return &gHooks[IMPL_NO_CONTEXT]; -} - -#endif +// ---------------------------------------------------------------------------- static __attribute__((noinline)) const char *egl_strerror(EGLint err) @@ -322,170 +261,14 @@ EGLContext getContext() { return tls->ctx; } -/*****************************************************************************/ - -/* - * we provide our own allocators for the GPU regions, these - * allocators go through surfaceflinger - */ - -static Mutex gRegionsLock; -static request_gpu_t gRegions; -static sp<ISurfaceComposer> gSurfaceManager; -ISurfaceComposer* GLES_localSurfaceManager = 0; - -const sp<ISurfaceComposer>& getSurfaceFlinger() -{ - Mutex::Autolock _l(gRegionsLock); - - /* - * There is a little bit of voodoo magic here. We want to access - * surfaceflinger for allocating GPU regions, however, when we are - * running as part of surfaceflinger, we want to bypass the - * service manager because surfaceflinger might not be registered yet. - * SurfaceFlinger will populate "GLES_localSurfaceManager" with its - * own address, so we can just use that. - */ - if (gSurfaceManager == 0) { - if (GLES_localSurfaceManager) { - // we're running in SurfaceFlinger's context - gSurfaceManager = GLES_localSurfaceManager; - } else { - // we're a remote process or not part of surfaceflinger, - // go through the service manager - sp<IServiceManager> sm = defaultServiceManager(); - if (sm != NULL) { - sp<IBinder> binder = sm->getService(String16("SurfaceFlinger")); - gSurfaceManager = interface_cast<ISurfaceComposer>(binder); - } - } - } - return gSurfaceManager; -} - -class GPURevokeRequester : public BnGPUCallback -{ -public: - virtual void gpuLost() { - LOGD("CONTEXT_LOST: Releasing GPU upon request from SurfaceFlinger."); - gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_HARDWARE_CONTEXT_LOST]; - } -}; - -static sp<GPURevokeRequester> gRevokerCallback; - - -static request_gpu_t* gpu_acquire(void* user) -{ - sp<ISurfaceComposer> server( getSurfaceFlinger() ); - - Mutex::Autolock _l(gRegionsLock); - if (server == NULL) { - return 0; - } - - ISurfaceComposer::gpu_info_t info; - - if (gRevokerCallback == 0) - gRevokerCallback = new GPURevokeRequester(); - - status_t err = server->requestGPU(gRevokerCallback, &info); - if (err != NO_ERROR) { - LOGD("requestGPU returned %d", err); - return 0; - } - - bool failed = false; - request_gpu_t* gpu = &gRegions; - memset(gpu, 0, sizeof(*gpu)); - - if (info.regs != 0) { - sp<IMemoryHeap> heap(info.regs->getMemory()); - if (heap != 0) { - int fd = heap->heapID(); - gpu->regs.fd = fd; - gpu->regs.base = info.regs->pointer(); - gpu->regs.size = info.regs->size(); - gpu->regs.user = info.regs.get(); -#if HAVE_ANDROID_OS - struct pmem_region region; - if (ioctl(fd, PMEM_GET_PHYS, ®ion) >= 0) - gpu->regs.phys = (void*)region.offset; -#endif - info.regs->incStrong(gpu); - } else { - LOGE("GPU register handle %p is invalid!", info.regs.get()); - failed = true; - } - } - - for (size_t i=0 ; i<info.count && !failed ; i++) { - sp<IMemory>& region(info.regions[i].region); - if (region != 0) { - sp<IMemoryHeap> heap(region->getMemory()); - if (heap != 0) { - const int fd = heap->heapID(); - gpu->gpu[i].fd = fd; - gpu->gpu[i].base = region->pointer(); - gpu->gpu[i].size = region->size(); - gpu->gpu[i].user = region.get(); - gpu->gpu[i].offset = info.regions[i].reserved; -#if HAVE_ANDROID_OS - struct pmem_region reg; - if (ioctl(fd, PMEM_GET_PHYS, ®) >= 0) - gpu->gpu[i].phys = (void*)reg.offset; -#endif - region->incStrong(gpu); - } else { - LOGE("GPU region handle [%d, %p] is invalid!", i, region.get()); - failed = true; - } - } - } - - if (failed) { - // something went wrong, clean up everything! - if (gpu->regs.user) { - static_cast<IMemory*>(gpu->regs.user)->decStrong(gpu); - for (size_t i=0 ; i<info.count ; i++) { - if (gpu->gpu[i].user) { - static_cast<IMemory*>(gpu->gpu[i].user)->decStrong(gpu); - } - } - } - } - - gpu->count = info.count; - return gpu; -} - -static int gpu_release(void*, request_gpu_t* gpu) -{ - sp<IMemory> regs; - - { // scope for lock - Mutex::Autolock _l(gRegionsLock); - regs = static_cast<IMemory*>(gpu->regs.user); - gpu->regs.user = 0; - if (regs != 0) regs->decStrong(gpu); - - for (int i=0 ; i<gpu->count ; i++) { - sp<IMemory> r(static_cast<IMemory*>(gpu->gpu[i].user)); - gpu->gpu[i].user = 0; - if (r != 0) r->decStrong(gpu); - } - } - - // there is a special transaction to relinquish the GPU - // (it will happen automatically anyway if we don't do this) - Parcel data, reply; - // NOTE: this transaction does not require an interface token - regs->asBinder()->transact(1000, data, &reply); - return 1; -} /*****************************************************************************/ +class ISurfaceComposer; +const sp<ISurfaceComposer>& getSurfaceFlinger(); +request_gpu_t* gpu_acquire(void* user); +int gpu_release(void*, request_gpu_t* gpu); + static __attribute__((noinline)) void *load_driver(const char* driver, gl_hooks_t* hooks) { @@ -576,18 +359,12 @@ static int cmp_configs(const void* a, const void *b) return c0<c1 ? -1 : (c0>c1 ? 1 : 0); } -static char const * const gVendorString = "Android"; -static char const * const gVersionString = "1.3 Android META-EGL"; -static char const * const gClientApiString = "OpenGL ES"; - struct extention_map_t { const char* name; - void (*address)(void); + __eglMustCastToProperFunctionPointerType address; }; static const extention_map_t gExtentionMap[] = { - { "eglSwapRectangleANDROID", (void(*)())&eglSwapRectangleANDROID }, - { "eglQueryStringConfigANDROID", (void(*)())&eglQueryStringConfigANDROID }, }; static extention_map_t gGLExtentionMap[MAX_NUMBER_OF_GL_EXTENSIONS]; @@ -604,109 +381,18 @@ static void(*findProcAddress(const char* name, } // ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- - -using namespace android; - - -// ---------------------------------------------------------------------------- -// extensions for the framework -// ---------------------------------------------------------------------------- - -void glColorPointerBounds(GLint size, GLenum type, GLsizei stride, - const GLvoid *ptr, GLsizei count) { - glColorPointer(size, type, stride, ptr); -} -void glNormalPointerBounds(GLenum type, GLsizei stride, - const GLvoid *pointer, GLsizei count) { - glNormalPointer(type, stride, pointer); -} -void glTexCoordPointerBounds(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer, GLsizei count) { - glTexCoordPointer(size, type, stride, pointer); -} -void glVertexPointerBounds(GLint size, GLenum type, - GLsizei stride, const GLvoid *pointer, GLsizei count) { - glVertexPointer(size, type, stride, pointer); -} - - -// ---------------------------------------------------------------------------- -// Actual GL wrappers -// ---------------------------------------------------------------------------- - -#if __OPTIMIZE__ && defined(__arm__) && !defined(__thumb__) && !USE_SLOW_BINDING && !GL_LOGGER - - #define API_ENTRY(_api) __attribute__((naked)) _api - #define CALL_GL_API(_api, ...) \ - asm volatile( \ - "mov r12, #0xFFFF0FFF \n" \ - "ldr r12, [r12, #-15] \n" \ - "ldr r12, [r12, %[tls]] \n" \ - "cmp r12, #0 \n" \ - "ldrne pc, [r12, %[api]] \n" \ - "bx lr \n" \ - : \ - : [tls] "J"(TLS_SLOT_OPENGL_API*4), \ - [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api)) \ - : \ - ); - - #define CALL_GL_API_RETURN(_api, ...) \ - CALL_GL_API(_api, __VA_ARGS__) \ - return 0; // placate gcc's warnings. never reached. - -#else - - #define API_ENTRY(_api) _api - #if GL_LOGGER - - #define CALL_GL_API(_api, ...) \ - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ - log_##_api(__VA_ARGS__); \ - _c->_api(__VA_ARGS__); - - #define CALL_GL_API_RETURN(_api, ...) \ - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ - log_##_api(__VA_ARGS__); \ - return _c->_api(__VA_ARGS__) - - #else - - #define CALL_GL_API(_api, ...) \ - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ - _c->_api(__VA_ARGS__); - - #define CALL_GL_API_RETURN(_api, ...) \ - gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ - return _c->_api(__VA_ARGS__) - - #endif - -#endif - -#include "gl_api.cpp" - -#undef API_ENTRY -#undef CALL_GL_API -#undef CALL_GL_API_RETURN - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- static int gl_context_lost() { - setGlThreadSpecific(&gHooks[IMPL_HARDWARE_CONTEXT_LOST]); + setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]); return 0; } static int egl_context_lost() { - setGlThreadSpecific(&gHooks[IMPL_HARDWARE_CONTEXT_LOST]); + setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]); return EGL_FALSE; } static EGLBoolean egl_context_lost_swap_buffers(void*, void*) { usleep(100000); // don't use all the CPU - setGlThreadSpecific(&gHooks[IMPL_HARDWARE_CONTEXT_LOST]); + setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]); return EGL_FALSE; } static GLint egl_context_lost_get_error() { @@ -721,11 +407,14 @@ static void gl_no_context() { } static void early_egl_init(void) { -#if !defined(HAVE_ANDROID_OS) || USE_SLOW_BINDING || GL_LOGGER +#if !USE_FAST_TLS_KEY pthread_key_create(&gGLWrapperKey, NULL); #endif uint32_t addr = (uint32_t)((void*)gl_no_context); - android_memset32((uint32_t*)(void*)&gHooks[IMPL_NO_CONTEXT], addr, sizeof(gHooks[IMPL_NO_CONTEXT])); + android_memset32( + (uint32_t*)(void*)&gHooks[IMPL_NO_CONTEXT], + addr, + sizeof(gHooks[IMPL_NO_CONTEXT])); setGlThreadSpecific(&gHooks[IMPL_NO_CONTEXT]); } @@ -802,25 +491,12 @@ static EGLBoolean validate_display_surface(EGLDisplay dpy, EGLSurface surface) return EGL_TRUE; } -static void add_extension(egl_display_t* dp, char const*& p, const char* ext) -{ - if (!strstr(p, ext)) { - p = (char const*)realloc((void*)p, strlen(p) + 1 + strlen(ext) + 1); - strcat((char*)p, " "); - strcat((char*)p, ext); - } - if (!strstr(dp->extensionsString, ext)) { - char const*& es = dp->extensionsString; - es = (char const*)realloc((void*)es, strlen(es) + 1 + strlen(ext) + 1); - strcat((char*)es, " "); - strcat((char*)es, ext); - } -} - // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- +using namespace android; + EGLDisplay eglGetDisplay(NativeDisplayType display) { if (sEarlyInitState) { @@ -854,38 +530,32 @@ EGLDisplay eglGetDisplay(NativeDisplayType display) property_get("debug.egl.hw", value, "1"); if (atoi(value) != 0) { cnx->hooks = &gHooks[IMPL_HARDWARE]; - property_get("debug.egl.profiler", value, "0"); - if (atoi(value) == 0) { - cnx->dso = load_driver("libhgl.so", cnx->hooks); - } else { - LOGW("Using instrumented h/w OpenGL ES library"); - cnx->dso = load_driver("libhgld.so", cnx->hooks); - } + cnx->dso = load_driver("libhgl.so", cnx->hooks); } else { LOGD("3D hardware acceleration is disabled"); } } if (cnx->dso && d->dpys[IMPL_HARDWARE]==EGL_NO_DISPLAY) { android_memset32( - (uint32_t*)(void*)&gHooks[IMPL_HARDWARE_CONTEXT_LOST].gl, + (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].gl, (uint32_t)((void*)gl_context_lost), - sizeof(gHooks[IMPL_HARDWARE_CONTEXT_LOST].gl)); + sizeof(gHooks[IMPL_CONTEXT_LOST].gl)); android_memset32( - (uint32_t*)(void*)&gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl, + (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].egl, (uint32_t)((void*)egl_context_lost), - sizeof(gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl)); + sizeof(gHooks[IMPL_CONTEXT_LOST].egl)); android_memset32( - (uint32_t*)(void*)&gHooks[IMPL_HARDWARE_CONTEXT_LOST].ext, + (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].ext, (uint32_t)((void*)ext_context_lost), - sizeof(gHooks[IMPL_HARDWARE_CONTEXT_LOST].ext)); + sizeof(gHooks[IMPL_CONTEXT_LOST].ext)); - gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl.eglSwapBuffers = + gHooks[IMPL_CONTEXT_LOST].egl.eglSwapBuffers = egl_context_lost_swap_buffers; - gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl.eglGetError = + gHooks[IMPL_CONTEXT_LOST].egl.eglGetError = egl_context_lost_get_error; - gHooks[IMPL_HARDWARE_CONTEXT_LOST].egl.eglTerminate = + gHooks[IMPL_CONTEXT_LOST].egl.eglTerminate = gHooks[IMPL_HARDWARE].egl.eglTerminate; d->dpys[IMPL_HARDWARE] = cnx->hooks->egl.eglGetDisplay(display); @@ -913,8 +583,8 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); if (android_atomic_inc(&dp->refs) > 0) { - if (major != NULL) *major = 1; - if (minor != NULL) *minor = 2; + if (major != NULL) *major = VERSION_MAJOR; + if (minor != NULL) *minor = VERSION_MINOR; return EGL_TRUE; } @@ -923,7 +593,7 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) // initialize each EGL and // build our own extension string first, based on the extension we know // and the extension supported by our client implementation - dp->extensionsString = strdup("EGL_ANDROID_query_string_config"); + dp->extensionsString = strdup(gExtensionString); for (int i=0 ; i<2 ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; cnx->major = -1; @@ -947,54 +617,16 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) dp->queryString[i].clientApi = cnx->hooks->egl.eglQueryString(dp->dpys[i], EGL_CLIENT_APIS); - // Dynamically insert extensions we know about - if (cnx->hooks->egl.eglSwapRectangleANDROID) - add_extension(dp, dp->queryString[i].extensions, - "EGL_ANDROID_swap_rectangle"); - - if (cnx->hooks->egl.eglQueryStringConfigANDROID) - add_extension(dp, dp->queryString[i].extensions, - "EGL_ANDROID_query_string_config"); } else { LOGD("%d: eglInitialize() failed (%s)", i, egl_strerror(cnx->hooks->egl.eglGetError())); } } - // Build the extension list that depends on the current config. - // It is the intersection of our extension list and the - // underlying EGL's extensions list EGLBoolean res = EGL_FALSE; for (int i=0 ; i<2 ; i++) { egl_connection_t* const cnx = &gEGLImpl[i]; if (cnx->dso && cnx->major>=0 && cnx->minor>=0) { - char const* const their_extensions = dp->queryString[i].extensions; - char* our_extensions = strdup(dp->extensionsString); - char* const our_extensions_org = our_extensions; - char* extensions_config = (char*)calloc(strlen(our_extensions)+2, 1); - char* p; - do { - p = strchr(our_extensions, ' '); - if (p) *p++ = 0; - else p = strchr(our_extensions, 0); - if (strstr(their_extensions, our_extensions)) { - strcat(extensions_config, our_extensions); - strcat(extensions_config, " "); - } - our_extensions = p; - } while (*p); - free((void*)our_extensions_org); - - // remove the trailing white space - if (extensions_config[0] != 0) { - size_t l = strlen(extensions_config) - 1; // new size - extensions_config[l] = 0; // remove the trailing white space - extensions_config = (char*)realloc(extensions_config, l+1); - } else { - extensions_config = (char*)realloc(extensions_config, 1); - } - dp->queryString[i].extensions_config = extensions_config; - EGLint n; if (cnx->hooks->egl.eglGetConfigs(dp->dpys[i], 0, 0, &n)) { dp->configs[i] = (EGLConfig*)malloc(sizeof(EGLConfig)*n); @@ -1016,8 +648,8 @@ EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) } if (res == EGL_TRUE) { - if (major != NULL) *major = 1; - if (minor != NULL) *minor = 2; + if (major != NULL) *major = VERSION_MAJOR; + if (minor != NULL) *minor = VERSION_MINOR; return EGL_TRUE; } return setError(EGL_NOT_INITIALIZED, EGL_FALSE); @@ -1042,7 +674,6 @@ EGLBoolean eglTerminate(EGLDisplay dpy) * threads around). */ free(dp->configs[i]); - free((void*)dp->queryString[i].extensions_config); free((void*)dp->queryString[i].extensions); dp->numConfigs[i] = 0; dp->dpys[i] = EGL_NO_DISPLAY; @@ -1486,7 +1117,7 @@ EGLint eglGetError(void) void (*eglGetProcAddress(const char *procname))() { - void (*addr)(); + __eglMustCastToProperFunctionPointerType addr; addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap)); if (addr) return addr; @@ -1570,7 +1201,7 @@ const char* eglQueryString(EGLDisplay dpy, EGLint name) case EGL_VERSION: return gVersionString; case EGL_EXTENSIONS: - return dp->extensionsString; + return gExtensionString; case EGL_CLIENT_APIS: return gClientApiString; } @@ -1730,34 +1361,3 @@ EGLSurface eglCreatePbufferFromClientBuffer( } return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); } - -// ---------------------------------------------------------------------------- -// Android extentions -// ---------------------------------------------------------------------------- - -EGLBoolean eglSwapRectangleANDROID( - EGLDisplay dpy, EGLSurface draw, - EGLint l, EGLint t, EGLint w, EGLint h) -{ - if (!validate_display_surface(dpy, draw)) - return EGL_FALSE; - egl_display_t const * const dp = get_display(dpy); - egl_surface_t const * const s = get_surface(draw); - if (s->cnx->hooks->egl.eglSwapRectangleANDROID) { - return s->cnx->hooks->egl.eglSwapRectangleANDROID( - dp->dpys[s->impl], s->surface, l, t, w, h); - } - return setError(EGL_BAD_SURFACE, EGL_FALSE); -} - -const char* eglQueryStringConfigANDROID( - EGLDisplay dpy, EGLConfig config, EGLint name) -{ - egl_display_t const* dp = 0; - int i=0, index=0; - egl_connection_t* cnx = validate_display_config(dpy, config, dp, i, index); - if (cnx) { - return dp->queryString[i].extensions_config; - } - return setError(EGL_BAD_PARAMETER, (const char *)0); -} diff --git a/opengl/libs/EGL/gpu.cpp b/opengl/libs/EGL/gpu.cpp new file mode 100644 index 0000000000..3f9fd63405 --- /dev/null +++ b/opengl/libs/EGL/gpu.cpp @@ -0,0 +1,212 @@ +/* + ** Copyright 2007, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#define LOG_TAG "EGL" + +#include <ctype.h> +#include <string.h> +#include <errno.h> + +#include <sys/ioctl.h> + +#if HAVE_ANDROID_OS +#include <linux/android_pmem.h> +#endif + +#include <cutils/log.h> +#include <cutils/properties.h> + +#include <utils/IMemory.h> +#include <utils/threads.h> +#include <utils/IServiceManager.h> +#include <utils/IPCThreadState.h> +#include <utils/Parcel.h> + +#include <ui/EGLDisplaySurface.h> +#include <ui/ISurfaceComposer.h> + +#include "hooks.h" +#include "egl_impl.h" + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +/* + * we provide our own allocators for the GPU regions, these + * allocators go through surfaceflinger + */ + +static Mutex gRegionsLock; +static request_gpu_t gRegions; +static sp<ISurfaceComposer> gSurfaceManager; +ISurfaceComposer* GLES_localSurfaceManager = 0; + +extern egl_connection_t gEGLImpl[2]; + +const sp<ISurfaceComposer>& getSurfaceFlinger() +{ + Mutex::Autolock _l(gRegionsLock); + + /* + * There is a little bit of voodoo magic here. We want to access + * surfaceflinger for allocating GPU regions, however, when we are + * running as part of surfaceflinger, we want to bypass the + * service manager because surfaceflinger might not be registered yet. + * SurfaceFlinger will populate "GLES_localSurfaceManager" with its + * own address, so we can just use that. + */ + if (gSurfaceManager == 0) { + if (GLES_localSurfaceManager) { + // we're running in SurfaceFlinger's context + gSurfaceManager = GLES_localSurfaceManager; + } else { + // we're a remote process or not part of surfaceflinger, + // go through the service manager + sp<IServiceManager> sm = defaultServiceManager(); + if (sm != NULL) { + sp<IBinder> binder = sm->getService(String16("SurfaceFlinger")); + gSurfaceManager = interface_cast<ISurfaceComposer>(binder); + } + } + } + return gSurfaceManager; +} + +class GPURevokeRequester : public BnGPUCallback +{ +public: + virtual void gpuLost() { + LOGD("CONTEXT_LOST: Releasing GPU upon request from SurfaceFlinger."); + gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST]; + } +}; + +static sp<GPURevokeRequester> gRevokerCallback; + + +request_gpu_t* gpu_acquire(void* user) +{ + sp<ISurfaceComposer> server( getSurfaceFlinger() ); + + Mutex::Autolock _l(gRegionsLock); + if (server == NULL) { + return 0; + } + + ISurfaceComposer::gpu_info_t info; + + if (gRevokerCallback == 0) + gRevokerCallback = new GPURevokeRequester(); + + status_t err = server->requestGPU(gRevokerCallback, &info); + if (err != NO_ERROR) { + LOGD("requestGPU returned %d", err); + return 0; + } + + bool failed = false; + request_gpu_t* gpu = &gRegions; + memset(gpu, 0, sizeof(*gpu)); + + if (info.regs != 0) { + sp<IMemoryHeap> heap(info.regs->getMemory()); + if (heap != 0) { + int fd = heap->heapID(); + gpu->regs.fd = fd; + gpu->regs.base = info.regs->pointer(); + gpu->regs.size = info.regs->size(); + gpu->regs.user = info.regs.get(); +#if HAVE_ANDROID_OS + struct pmem_region region; + if (ioctl(fd, PMEM_GET_PHYS, ®ion) >= 0) + gpu->regs.phys = (void*)region.offset; +#endif + info.regs->incStrong(gpu); + } else { + LOGE("GPU register handle %p is invalid!", info.regs.get()); + failed = true; + } + } + + for (size_t i=0 ; i<info.count && !failed ; i++) { + sp<IMemory>& region(info.regions[i].region); + if (region != 0) { + sp<IMemoryHeap> heap(region->getMemory()); + if (heap != 0) { + const int fd = heap->heapID(); + gpu->gpu[i].fd = fd; + gpu->gpu[i].base = region->pointer(); + gpu->gpu[i].size = region->size(); + gpu->gpu[i].user = region.get(); + gpu->gpu[i].offset = info.regions[i].reserved; +#if HAVE_ANDROID_OS + struct pmem_region reg; + if (ioctl(fd, PMEM_GET_PHYS, ®) >= 0) + gpu->gpu[i].phys = (void*)reg.offset; +#endif + region->incStrong(gpu); + } else { + LOGE("GPU region handle [%d, %p] is invalid!", i, region.get()); + failed = true; + } + } + } + + if (failed) { + // something went wrong, clean up everything! + if (gpu->regs.user) { + static_cast<IMemory*>(gpu->regs.user)->decStrong(gpu); + for (size_t i=0 ; i<info.count ; i++) { + if (gpu->gpu[i].user) { + static_cast<IMemory*>(gpu->gpu[i].user)->decStrong(gpu); + } + } + } + } + + gpu->count = info.count; + return gpu; +} + +int gpu_release(void*, request_gpu_t* gpu) +{ + sp<IMemory> regs; + + { // scope for lock + Mutex::Autolock _l(gRegionsLock); + regs = static_cast<IMemory*>(gpu->regs.user); + gpu->regs.user = 0; + if (regs != 0) regs->decStrong(gpu); + + for (int i=0 ; i<gpu->count ; i++) { + sp<IMemory> r(static_cast<IMemory*>(gpu->gpu[i].user)); + gpu->gpu[i].user = 0; + if (r != 0) r->decStrong(gpu); + } + } + + // there is a special transaction to relinquish the GPU + // (it will happen automatically anyway if we don't do this) + Parcel data, reply; + // NOTE: this transaction does not require an interface token + regs->asBinder()->transact(1000, data, &reply); + return 1; +} + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- diff --git a/opengl/libs/GLES_CM/gl.cpp b/opengl/libs/GLES_CM/gl.cpp new file mode 100644 index 0000000000..865cf44362 --- /dev/null +++ b/opengl/libs/GLES_CM/gl.cpp @@ -0,0 +1,116 @@ +/* + ** Copyright 2007, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#define LOG_TAG "GLES_CM" + +#include <ctype.h> +#include <string.h> +#include <errno.h> + +#include <sys/ioctl.h> + +#include <GLES/gl.h> +#include <GLES/glext.h> + +#include <cutils/log.h> +#include <cutils/properties.h> + +#include "hooks.h" + +using namespace android; + +// ---------------------------------------------------------------------------- +// extensions for the framework +// ---------------------------------------------------------------------------- + +void glColorPointerBounds(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr, GLsizei count) { + glColorPointer(size, type, stride, ptr); +} +void glNormalPointerBounds(GLenum type, GLsizei stride, + const GLvoid *pointer, GLsizei count) { + glNormalPointer(type, stride, pointer); +} +void glTexCoordPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count) { + glTexCoordPointer(size, type, stride, pointer); +} +void glVertexPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count) { + glVertexPointer(size, type, stride, pointer); +} + +// ---------------------------------------------------------------------------- +// Actual GL entry-points +// ---------------------------------------------------------------------------- + +#if GL_LOGGER +# include "gl_logger.h" +# define GL_LOGGER_IMPL(_x) _x +#else +# define GL_LOGGER_IMPL(_x) +#endif + +#undef API_ENTRY +#undef CALL_GL_API +#undef CALL_GL_API_RETURN + +#if USE_FAST_TLS_KEY + + #define API_ENTRY(_api) __attribute__((naked)) _api + + #define CALL_GL_API(_api, ...) \ + asm volatile( \ + "mov r12, #0xFFFF0FFF \n" \ + "ldr r12, [r12, #-15] \n" \ + "ldr r12, [r12, %[tls]] \n" \ + "cmp r12, #0 \n" \ + "ldrne pc, [r12, %[api]] \n" \ + "bx lr \n" \ + : \ + : [tls] "J"(TLS_SLOT_OPENGL_API*4), \ + [api] "J"(__builtin_offsetof(gl_hooks_t, gl._api)) \ + : \ + ); + + #define CALL_GL_API_RETURN(_api, ...) \ + CALL_GL_API(_api, __VA_ARGS__) \ + return 0; // placate gcc's warnings. never reached. + +#else + + #define API_ENTRY(_api) _api + + #define CALL_GL_API(_api, ...) \ + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ + GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); ) \ + _c->_api(__VA_ARGS__) + + #define CALL_GL_API_RETURN(_api, ...) \ + gl_hooks_t::gl_t const * const _c = &getGlThreadSpecific()->gl; \ + GL_LOGGER_IMPL( log_##_api(__VA_ARGS__); ) \ + return _c->_api(__VA_ARGS__) + +#endif + +extern "C" { +#include "gl_api.in" +} + +#undef API_ENTRY +#undef CALL_GL_API +#undef CALL_GL_API_RETURN + diff --git a/opengl/libGLES_CM/gl_api.cpp b/opengl/libs/GLES_CM/gl_api.in index ed3bdaa838..9234ef2738 100644 --- a/opengl/libGLES_CM/gl_api.cpp +++ b/opengl/libs/GLES_CM/gl_api.in @@ -415,7 +415,7 @@ void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) { CALL_GL_API(glTexEnvxv, target, pname, params); } -void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLenum internalformat, +void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, diff --git a/opengl/libGLES_CM/gl_logger.cpp b/opengl/libs/GLES_CM/gl_logger.cpp index 14b5a399e2..27be5c9bac 100644 --- a/opengl/libGLES_CM/gl_logger.cpp +++ b/opengl/libs/GLES_CM/gl_logger.cpp @@ -23,7 +23,10 @@ #include <sys/ioctl.h> -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES/gl.h> +#include <GLES/glext.h> #include <cutils/log.h> #include <cutils/atomic.h> @@ -33,13 +36,13 @@ #include "gl_logger.h" +#undef NELEM +#define NELEM(x) (sizeof(x)/sizeof(*(x))) + // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- -#undef NELEM -#define NELEM(x) (sizeof(x)/sizeof(*(x))) - template<typename T> static int binarySearch(T const sortedArray[], int first, int last, EGLint key) { @@ -226,12 +229,6 @@ private: int mNumParams; }; -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- - -using namespace android; - #define API_ENTRY(api) log_##api #define CALL_GL_API(_x, ...) #define CALL_GL_API_RETURN(_x, ...) return(0); @@ -785,7 +782,7 @@ void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) { GLLog("glTexEnvxv") << GLLogEnum(target) << GLLogEnum(pname) << GLLogBuffer<GLfixed>(params); } -void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLenum internalformat, +void API_ENTRY(glTexImage2D)( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, @@ -1057,3 +1054,7 @@ GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed* mantissa, GLint* exponent) { GLLog("glQueryMatrixxOES") << GLLogBuffer<GLfixed>(mantissa, 16) << GLLogBuffer<GLfixed>(exponent, 16); CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent); } + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- diff --git a/opengl/libGLES_CM/egl_entries.cpp b/opengl/libs/egl_entries.in index ba46f40647..33b4c654d2 100644 --- a/opengl/libGLES_CM/egl_entries.cpp +++ b/opengl/libs/egl_entries.in @@ -23,7 +23,7 @@ EGL_ENTRY(EGLBoolean, eglSwapBuffers, EGLDisplay, EGLSurface) EGL_ENTRY(EGLBoolean, eglCopyBuffers, EGLDisplay, EGLSurface, NativePixmapType) EGL_ENTRY(EGLint, eglGetError, void) EGL_ENTRY(const char*, eglQueryString, EGLDisplay, EGLint) -EGL_ENTRY(proc_t, eglGetProcAddress, const char *) +EGL_ENTRY(__eglMustCastToProperFunctionPointerType, eglGetProcAddress, const char *) /* EGL 1.1 */ @@ -40,7 +40,6 @@ EGL_ENTRY(EGLBoolean, eglWaitClient, void) EGL_ENTRY(EGLBoolean, eglReleaseThread, void) EGL_ENTRY(EGLSurface, eglCreatePbufferFromClientBuffer, EGLDisplay, EGLenum, EGLClientBuffer, EGLConfig, const EGLint *) -/* Android extentions */ +/* EGL 1.3 */ -EGL_ENTRY(EGLBoolean, eglSwapRectangleANDROID, EGLDisplay, EGLSurface , EGLint, EGLint, EGLint, EGLint) -EGL_ENTRY(const char*, eglQueryStringConfigANDROID, EGLDisplay, EGLConfig, EGLint) +/* EGL 1.4 */ diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h new file mode 100644 index 0000000000..62ce3fce17 --- /dev/null +++ b/opengl/libs/egl_impl.h @@ -0,0 +1,43 @@ +/* + ** Copyright 2007, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#ifndef ANDROID_EGL_IMPL_H +#define ANDROID_EGL_IMPL_H + +#include <ctype.h> + +#include <EGL/egl.h> + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +struct gl_hooks_t; + +struct egl_connection_t +{ + void volatile * dso; + gl_hooks_t * hooks; + EGLint major; + EGLint minor; + int unavailable; +}; + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +#endif /* ANDROID_EGL_IMPL_H */ diff --git a/opengl/libGLES_CM/gl_entries.cpp b/opengl/libs/gl_entries.in index 3279322961..b97e8fe3c4 100644 --- a/opengl/libGLES_CM/gl_entries.cpp +++ b/opengl/libs/gl_entries.in @@ -101,7 +101,7 @@ GL_ENTRY(void, glCompressedTexImage2D, GLenum, GLint, GLenum, GLsizei, GLsize GL_ENTRY(void, glCompressedTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*) GL_ENTRY(void, glCopyTexImage2D, GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint) GL_ENTRY(void, glCopyTexSubImage2D, GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei) -GL_ENTRY(void, glTexImage2D, GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*) +GL_ENTRY(void, glTexImage2D, GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*) GL_ENTRY(void, glTexSubImage2D, GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*) GL_ENTRY(void, glReadPixels, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *) diff --git a/opengl/libGLES_CM/gl_enums.in b/opengl/libs/gl_enums.in index ffc2fad430..ffc2fad430 100644 --- a/opengl/libGLES_CM/gl_enums.in +++ b/opengl/libs/gl_enums.in diff --git a/opengl/libGLES_CM/gl_logger.h b/opengl/libs/gl_logger.h index 59e31c7ece..ce85dd1ad0 100644 --- a/opengl/libGLES_CM/gl_logger.h +++ b/opengl/libs/gl_logger.h @@ -17,10 +17,10 @@ #ifndef ANDROID_GL_LOGGER_H #define ANDROID_GL_LOGGER_H -extern "C" { +namespace android { #define GL_ENTRY(r, api, ...) r log_##api(__VA_ARGS__); -#include "gl_entries.cpp" +#include "gl_entries.in" #undef GL_ENTRY -}; +}; // namespace android #endif /* ANDROID_GL_LOGGER_H */ diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h new file mode 100644 index 0000000000..63fb017675 --- /dev/null +++ b/opengl/libs/hooks.h @@ -0,0 +1,134 @@ +/* + ** Copyright 2007, The Android Open Source Project + ** + ** Licensed under the Apache License, Version 2.0 (the "License"); + ** you may not use this file except in compliance with the License. + ** You may obtain a copy of the License at + ** + ** http://www.apache.org/licenses/LICENSE-2.0 + ** + ** Unless required by applicable law or agreed to in writing, software + ** distributed under the License is distributed on an "AS IS" BASIS, + ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ + +#ifndef ANDROID_GLES_CM_HOOKS_H +#define ANDROID_GLES_CM_HOOKS_H + +#include <ctype.h> +#include <string.h> +#include <errno.h> + +#include <EGL/egl.h> +#include <GLES/gl.h> + +#define GL_LOGGER 0 +#if !defined(__arm__) +#define USE_SLOW_BINDING 1 +#else +#define USE_SLOW_BINDING 0 +#endif +#undef NELEM +#define NELEM(x) (sizeof(x)/sizeof(*(x))) +#define MAX_NUMBER_OF_GL_EXTENSIONS 32 + + +#if defined(HAVE_ANDROID_OS) && !USE_SLOW_BINDING && !GL_LOGGER && __OPTIMIZE__ +#define USE_FAST_TLS_KEY 1 +#else +#define USE_FAST_TLS_KEY 0 +#endif + +#if USE_FAST_TLS_KEY +# include <bionic_tls.h> /* special private C library header */ +#endif + +// ---------------------------------------------------------------------------- +namespace android { +// ---------------------------------------------------------------------------- + +// EGLDisplay are global, not attached to a given thread +const unsigned int NUM_DISPLAYS = 1; + +enum { + IMPL_HARDWARE = 0, + IMPL_SOFTWARE, + IMPL_CONTEXT_LOST, + IMPL_NO_CONTEXT, + + IMPL_NUM_IMPLEMENTATIONS +}; + +// ---------------------------------------------------------------------------- + +// GL / EGL hooks + +#undef GL_ENTRY +#undef EGL_ENTRY +#define GL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); +#define EGL_ENTRY(_r, _api, ...) _r (*_api)(__VA_ARGS__); + +struct gl_hooks_t { + struct gl_t { + #include "gl_entries.in" + } gl; + struct egl_t { + #include "egl_entries.in" + } egl; + struct gl_ext_t { + void (*extensions[MAX_NUMBER_OF_GL_EXTENSIONS])(void); + } ext; +}; +#undef GL_ENTRY +#undef EGL_ENTRY + + +// ---------------------------------------------------------------------------- + +extern gl_hooks_t gHooks[IMPL_NUM_IMPLEMENTATIONS]; +extern pthread_key_t gGLWrapperKey; + +#if USE_FAST_TLS_KEY + +// We have a dedicated TLS slot in bionic +static inline gl_hooks_t const * volatile * get_tls_hooks() { + volatile void *tls_base = __get_tls(); + gl_hooks_t const * volatile * tls_hooks = + reinterpret_cast<gl_hooks_t const * volatile *>(tls_base); + return tls_hooks; +} + +static inline void setGlThreadSpecific(gl_hooks_t const *value) { + gl_hooks_t const * volatile * tls_hooks = get_tls_hooks(); + tls_hooks[TLS_SLOT_OPENGL_API] = value; +} + +static gl_hooks_t const* getGlThreadSpecific() { + gl_hooks_t const * volatile * tls_hooks = get_tls_hooks(); + gl_hooks_t const* hooks = tls_hooks[TLS_SLOT_OPENGL_API]; + if (hooks) return hooks; + return &gHooks[IMPL_NO_CONTEXT]; +} + +#else + +static inline void setGlThreadSpecific(gl_hooks_t const *value) { + pthread_setspecific(gGLWrapperKey, value); +} + +static gl_hooks_t const* getGlThreadSpecific() { + gl_hooks_t const* hooks = static_cast<gl_hooks_t*>(pthread_getspecific(gGLWrapperKey)); + if (hooks) return hooks; + return &gHooks[IMPL_NO_CONTEXT]; +} + +#endif + + +// ---------------------------------------------------------------------------- +}; // namespace android +// ---------------------------------------------------------------------------- + +#endif /* ANDROID_GLES_CM_HOOKS_H */ diff --git a/opengl/libGLES_CM/enumextract.sh b/opengl/libs/tools/enumextract.sh index 570730215f..570730215f 100644 --- a/opengl/libGLES_CM/enumextract.sh +++ b/opengl/libs/tools/enumextract.sh diff --git a/opengl/tests/angeles/Android.mk b/opengl/tests/angeles/Android.mk index 41673cbe41..46958d3c3c 100644 --- a/opengl/tests/angeles/Android.mk +++ b/opengl/tests/angeles/Android.mk @@ -3,7 +3,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= app-linux.c demo.c.arm -LOCAL_SHARED_LIBRARIES := libGLES_CM libui +LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM libui LOCAL_MODULE:= angeles LOCAL_MODULE_TAGS := tests include $(BUILD_EXECUTABLE) @@ -11,7 +11,7 @@ include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_SRC_FILES:= gpustate.c -LOCAL_SHARED_LIBRARIES := libGLES_CM +LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM LOCAL_MODULE:= gpustate LOCAL_MODULE_TAGS := tests include $(BUILD_EXECUTABLE) diff --git a/opengl/tests/angeles/app-linux.c b/opengl/tests/angeles/app-linux.c index d439eb2fbf..7d0d320a32 100644 --- a/opengl/tests/angeles/app-linux.c +++ b/opengl/tests/angeles/app-linux.c @@ -49,7 +49,8 @@ #include <stdio.h> #include <sys/time.h> -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <GLES/gl.h> #include "app.h" diff --git a/opengl/tests/filter/Android.mk b/opengl/tests/filter/Android.mk index 1c4253c2c0..a448f0d461 100644 --- a/opengl/tests/filter/Android.mk +++ b/opengl/tests/filter/Android.mk @@ -6,7 +6,8 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils \ - libGLES_CM \ + libEGL \ + libGLESv1_CM \ libui LOCAL_MODULE:= test-opengl-filter diff --git a/opengl/tests/filter/filter.c b/opengl/tests/filter/filter.c index c8bac06cd5..de9711963e 100644 --- a/opengl/tests/filter/filter.c +++ b/opengl/tests/filter/filter.c @@ -1,7 +1,9 @@ #include <stdlib.h> #include <stdio.h> -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <GLES/gl.h> +#include <GLES/glext.h> int main(int argc, char** argv) { @@ -40,6 +42,9 @@ int main(int argc, char** argv) printf("using pbuffer\n"); EGLint attribs[] = { EGL_WIDTH, 320, EGL_HEIGHT, 480, EGL_NONE }; surface = eglCreatePbufferSurface(dpy, config, attribs); + if (surface == EGL_NO_SURFACE) { + printf("eglCreatePbufferSurface error %x\n", eglGetError()); + } } context = eglCreateContext(dpy, config, NULL, NULL); eglMakeCurrent(dpy, surface, surface, context); diff --git a/opengl/tests/finish/Android.mk b/opengl/tests/finish/Android.mk index f7b95edccb..26836c1caf 100644 --- a/opengl/tests/finish/Android.mk +++ b/opengl/tests/finish/Android.mk @@ -6,7 +6,8 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils \ - libGLES_CM \ + libEGL \ + libGLESv1_CM \ libui LOCAL_MODULE:= test-opengl-finish diff --git a/opengl/tests/finish/finish.c b/opengl/tests/finish/finish.c index 3afe227681..45fc7587be 100644 --- a/opengl/tests/finish/finish.c +++ b/opengl/tests/finish/finish.c @@ -20,7 +20,10 @@ #include <sched.h> #include <sys/resource.h> -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <GLES/gl.h> +#include <GLES/glext.h> + long long systemTime() { diff --git a/opengl/tests/sfsim/Android.mk b/opengl/tests/sfsim/Android.mk deleted file mode 100644 index 8a1a03cc42..0000000000 --- a/opengl/tests/sfsim/Android.mk +++ /dev/null @@ -1,15 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - egl_surface.cpp \ - sfsim.c - -LOCAL_SHARED_LIBRARIES := \ - libGLES_CM - -LOCAL_MODULE:= test-opengl-sfsim - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_EXECUTABLE) diff --git a/opengl/tests/sfsim/egl_surface.cpp b/opengl/tests/sfsim/egl_surface.cpp deleted file mode 100644 index b0777f8c1c..0000000000 --- a/opengl/tests/sfsim/egl_surface.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* - ** - ** Copyright 2008 The Android Open Source Project - ** - ** Licensed under the Apache License Version 2.0(the "License"); - ** you may not use this file except in compliance with the License. - ** You may obtain a copy of the License at - ** - ** http://www.apache.org/licenses/LICENSE-2.0 - ** - ** Unless required by applicable law or agreed to in writing software - ** distributed under the License is distributed on an "AS IS" BASIS - ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. - ** See the License for the specific language governing permissions and - ** limitations under the License. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/types.h> -#include <sys/mman.h> - -#include <GLES/egl.h> - -#include "egl_surface.h" - -#define LOGI(x...) do { printf("INFO: " x); } while (0) -#define LOGW(x...) do { printf("WARN: " x); } while (0) -#define LOGE(x...) do { printf("ERR: " x); } while (0) - -// ---------------------------------------------------------------------------- - -egl_native_window_t* android_createDisplaySurface() -{ - egl_native_window_t* s = new android::EGLDisplaySurface(); - s->memory_type = NATIVE_MEMORY_TYPE_GPU; - return s; -} - -#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) -#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) - -// ---------------------------------------------------------------------------- -namespace android { -// ---------------------------------------------------------------------------- - -EGLDisplaySurface::EGLDisplaySurface() - : EGLNativeSurface<EGLDisplaySurface>() -{ - egl_native_window_t::version = sizeof(egl_native_window_t); - egl_native_window_t::ident = 0; - egl_native_window_t::incRef = &EGLDisplaySurface::hook_incRef; - egl_native_window_t::decRef = &EGLDisplaySurface::hook_decRef; - egl_native_window_t::swapBuffers = &EGLDisplaySurface::hook_swapBuffers; - egl_native_window_t::setSwapRectangle = &EGLDisplaySurface::hook_setSwapRectangle; - egl_native_window_t::nextBuffer = &EGLDisplaySurface::hook_nextBuffer; - egl_native_window_t::connect = 0; - egl_native_window_t::disconnect = 0; - - mFb[0].data = 0; - mFb[1].data = 0; - egl_native_window_t::fd = mapFrameBuffer(); - if (egl_native_window_t::fd >= 0) { - const float in2mm = 25.4f; - float refreshRate = 1000000000000000LLU / ( - float( mInfo.upper_margin + mInfo.lower_margin + mInfo.yres ) - * ( mInfo.left_margin + mInfo.right_margin + mInfo.xres ) - * mInfo.pixclock); - - const GGLSurface& buffer = mFb[1 - mIndex]; - egl_native_window_t::width = buffer.width; - egl_native_window_t::height = buffer.height; - egl_native_window_t::stride = buffer.stride; - egl_native_window_t::format = buffer.format; - egl_native_window_t::base = intptr_t(mFb[0].data); - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - egl_native_window_t::flags = 0; - egl_native_window_t::xdpi = (mInfo.xres * in2mm) / mInfo.width; - egl_native_window_t::ydpi = (mInfo.yres * in2mm) / mInfo.height; - egl_native_window_t::fps = refreshRate; - egl_native_window_t::memory_type = NATIVE_MEMORY_TYPE_FB; - // no error, set the magic word - egl_native_window_t::magic = 0x600913; - } - mSwapCount = -1; - mPageFlipCount = 0; -} - -EGLDisplaySurface::~EGLDisplaySurface() -{ - magic = 0; - close(egl_native_window_t::fd); - munmap(mFb[0].data, mSize); - if (!(mFlags & PAGE_FLIP)) - free((void*)mFb[1].data); -} - -void EGLDisplaySurface::hook_incRef(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->incStrong(that); -} -void EGLDisplaySurface::hook_decRef(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->decStrong(that); -} -uint32_t EGLDisplaySurface::hook_swapBuffers(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - return that->swapBuffers(); -} -uint32_t EGLDisplaySurface::hook_nextBuffer(NativeWindowType window) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - return that->nextBuffer(); -} -void EGLDisplaySurface::hook_setSwapRectangle(NativeWindowType window, - int l, int t, int w, int h) { - EGLDisplaySurface* that = static_cast<EGLDisplaySurface*>(window); - that->setSwapRectangle(l, t, w, h); -} - -void EGLDisplaySurface::setSwapRectangle(int l, int t, int w, int h) -{ - mInfo.reserved[0] = 0x54445055; // "UPDT"; - mInfo.reserved[1] = (uint16_t)l | ((uint32_t)t << 16); - mInfo.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16); -} - -uint32_t EGLDisplaySurface::swapBuffers() -{ - if (!(mFlags & PAGE_FLIP)) - return 0; - - // do the actual flip - mIndex = 1 - mIndex; - mInfo.activate = FB_ACTIVATE_VBL; - mInfo.yoffset = mIndex ? mInfo.yres : 0; - if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1) { - LOGE("FBIOPUT_VSCREENINFO failed"); - return 0; - } - - /* - * this is a monstruous hack: Because the h/w accelerator is not able - * to render directly into the framebuffer, we need to copy its - * internal framebuffer out to the fb. the base address of the internal fb - * is given in oem[0]. - * All this is needed only in standalone mode, in SurfaceFlinger mode - * we control where the GPU renders. - */ - if (egl_native_window_t::memory_type == NATIVE_MEMORY_TYPE_GPU && oem[0]) { - // could use MDP here, but that's tricky because we need - // /dev/pmem_gpu* filedescriptor - const GGLSurface& buffer = mFb[mIndex]; - memcpy( buffer.data, - (void*)(oem[0] + egl_native_window_t::offset), - buffer.stride*buffer.height*2); - } - - // update the address of the buffer to draw to next - const GGLSurface& buffer = mFb[1 - mIndex]; - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - - mPageFlipCount++; - - // We don't support screen-size changes for now - return 0; -} - -int32_t EGLDisplaySurface::getPageFlipCount() const -{ - return mPageFlipCount; -} - -uint32_t EGLDisplaySurface::nextBuffer() -{ - // update the address of the buffer to draw to next - const GGLSurface& buffer = mFb[mIndex]; - egl_native_window_t::offset = - intptr_t(buffer.data) - egl_native_window_t::base; - return 0; -} - -int EGLDisplaySurface::mapFrameBuffer() -{ - char const * const device_template[] = { - "/dev/graphics/fb%u", - "/dev/fb%u", - 0 }; - int fd = -1; - int i=0; - char name[64]; - while ((fd==-1) && device_template[i]) { - snprintf(name, 64, device_template[i], 0); - fd = open(name, O_RDWR, 0); - i++; - } - if (fd < 0) - return -errno; - - struct fb_fix_screeninfo finfo; - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) - return -errno; - - struct fb_var_screeninfo info; - if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - return -errno; - - info.reserved[0] = 0; - info.reserved[1] = 0; - info.reserved[2] = 0; - info.xoffset = 0; - info.yoffset = 0; - info.yres_virtual = info.yres * 2; - info.bits_per_pixel = 16; - info.activate = FB_ACTIVATE_NOW; - - uint32_t flags = PAGE_FLIP; - if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) { - info.yres_virtual = info.yres; - flags &= ~PAGE_FLIP; - LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported"); - } - - if (info.yres_virtual < info.yres * 2) { - info.yres_virtual = info.yres; - flags &= ~PAGE_FLIP; - LOGW("page flipping not supported (yres_virtual=%d, requested=%d)", - info.yres_virtual, info.yres*2); - } - - if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - return -errno; - - int refreshRate = 1000000000000000LLU / - ( - uint64_t( info.upper_margin + info.lower_margin + info.yres ) - * ( info.left_margin + info.right_margin + info.xres ) - * info.pixclock - ); - - if (refreshRate == 0) { - // bleagh, bad info from the driver - refreshRate = 60*1000; // 60 Hz - } - - if (int(info.width) <= 0 || int(info.height) <= 0) { - // stupid driver, doesn't return that information - // default to Sooner's screen size (160 dpi) - info.width = 51; - info.height = 38; - } - - float xdpi = (info.xres * 25.4f) / info.width; - float ydpi = (info.yres * 25.4f) / info.height; - float fps = refreshRate / 1000.0f; - - LOGI( "using (fd=%d)\n" - "id = %s\n" - "xres = %d px\n" - "yres = %d px\n" - "xres_virtual = %d px\n" - "yres_virtual = %d px\n" - "bpp = %d\n" - "r = %2u:%u\n" - "g = %2u:%u\n" - "b = %2u:%u\n", - fd, - finfo.id, - info.xres, - info.yres, - info.xres_virtual, - info.yres_virtual, - info.bits_per_pixel, - info.red.offset, info.red.length, - info.green.offset, info.green.length, - info.blue.offset, info.blue.length - ); - - LOGI( "width = %d mm (%f dpi)\n" - "height = %d mm (%f dpi)\n" - "refresh rate = %.2f Hz\n", - info.width, xdpi, - info.height, ydpi, - fps - ); - - - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) - return -errno; - - if (finfo.smem_len <= 0) - return -errno; - - /* - * Open and map the display. - */ - - void* buffer = (uint16_t*) mmap( - 0, finfo.smem_len, - PROT_READ | PROT_WRITE, - MAP_SHARED, - fd, 0); - - if (buffer == MAP_FAILED) - return -errno; - - // at least for now, always clear the fb - memset(buffer, 0, finfo.smem_len); - - uint8_t* offscreen[2]; - offscreen[0] = (uint8_t*)buffer; - if (flags & PAGE_FLIP) { - offscreen[1] = (uint8_t*)buffer + finfo.line_length*info.yres; - } else { - offscreen[1] = (uint8_t*)malloc(finfo.smem_len); - if (offscreen[1] == 0) { - munmap(buffer, finfo.smem_len); - return -ENOMEM; - } - } - - mFlags = flags; - mInfo = info; - mFinfo = finfo; - mSize = finfo.smem_len; - mIndex = 0; - for (int i=0 ; i<2 ; i++) { - mFb[i].version = sizeof(GGLSurface); - mFb[i].width = info.xres; - mFb[i].height = info.yres; - mFb[i].stride = finfo.line_length / (info.bits_per_pixel >> 3); - mFb[i].data = (uint8_t*)(offscreen[i]); - mFb[i].format = NATIVE_PIXEL_FORMAT_RGB_565; - } - return fd; -} - -// ---------------------------------------------------------------------------- -}; // namespace android -// ---------------------------------------------------------------------------- diff --git a/opengl/tests/sfsim/egl_surface.h b/opengl/tests/sfsim/egl_surface.h deleted file mode 100644 index 70a94fcab9..0000000000 --- a/opengl/tests/sfsim/egl_surface.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_SIM_EGL_SURFACE_H -#define ANDROID_SIM_EGL_SURFACE_H - -#include <stdint.h> -#include <errno.h> -#include <sys/types.h> - -#include <GLES/eglnatives.h> - -#include <linux/fb.h> - -typedef struct { - ssize_t version; // always set to sizeof(GGLSurface) - uint32_t width; // width in pixels - uint32_t height; // height in pixels - int32_t stride; // stride in pixels - uint8_t* data; // pointer to the bits - uint8_t format; // pixel format - uint8_t rfu[3]; // must be zero - void* reserved; -} GGLSurface; - -// --------------------------------------------------------------------------- -namespace android { -// --------------------------------------------------------------------------- - -template <class TYPE> -class EGLNativeSurface : public egl_native_window_t -{ -public: - EGLNativeSurface() : mCount(0) { - memset(egl_native_window_t::reserved, 0, - sizeof(egl_native_window_t::reserved)); - memset(egl_native_window_t::reserved_proc, 0, - sizeof(egl_native_window_t::reserved_proc)); - memset(egl_native_window_t::oem, 0, - sizeof(egl_native_window_t::oem)); - } - inline void incStrong(void*) const { - /* in a real implementation, the inc must be atomic */ - mCount++; - } - inline void decStrong(void*) const { - /* in a real implementation, the dec must be atomic */ - if (--mCount == 1) { - delete static_cast<const TYPE*>(this); - } - } -protected: - EGLNativeSurface& operator = (const EGLNativeSurface& rhs); - EGLNativeSurface(const EGLNativeSurface& rhs); - inline ~EGLNativeSurface() { }; - mutable volatile int32_t mCount; -}; - - -class EGLDisplaySurface : public EGLNativeSurface<EGLDisplaySurface> -{ -public: - EGLDisplaySurface(); - ~EGLDisplaySurface(); - - int32_t getPageFlipCount() const; - -private: - static void hook_incRef(NativeWindowType window); - static void hook_decRef(NativeWindowType window); - static uint32_t hook_swapBuffers(NativeWindowType window); - static void hook_setSwapRectangle(NativeWindowType window, int l, int t, int w, int h); - static uint32_t hook_nextBuffer(NativeWindowType window); - - uint32_t swapBuffers(); - uint32_t nextBuffer(); - void setSwapRectangle(int l, int t, int w, int h); - - int mapFrameBuffer(); - - enum { - PAGE_FLIP = 0x00000001 - }; - GGLSurface mFb[2]; - int mIndex; - uint32_t mFlags; - size_t mSize; - fb_var_screeninfo mInfo; - fb_fix_screeninfo mFinfo; - int32_t mPageFlipCount; - int32_t mSwapCount; - uint32_t mFeatureFlags; -}; - -// --------------------------------------------------------------------------- -}; // namespace android -// --------------------------------------------------------------------------- - -#endif // ANDROID_SIM_EGL_SURFACE_H - diff --git a/opengl/tests/sfsim/sfsim.c b/opengl/tests/sfsim/sfsim.c deleted file mode 100644 index 14ba490d70..0000000000 --- a/opengl/tests/sfsim/sfsim.c +++ /dev/null @@ -1,112 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> - -#include <GLES/egl.h> - -int main(int argc, char** argv) -{ - if (argc != 2) { - printf("usage: %s <0-6>\n", argv[0]); - return 0; - } - - const int test = atoi(argv[1]); - - EGLint s_configAttribs[] = { - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, - EGL_NONE - }; - - EGLint numConfigs = -1; - EGLint majorVersion; - EGLint minorVersion; - EGLConfig config; - EGLContext context; - EGLSurface surface; - EGLint w, h; - - EGLDisplay dpy; - - dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - eglInitialize(dpy, &majorVersion, &minorVersion); - eglChooseConfig(dpy, s_configAttribs, &config, 1, &numConfigs); - surface = eglCreateWindowSurface(dpy, config, - android_createDisplaySurface(), NULL); - context = eglCreateContext(dpy, config, NULL, NULL); - eglMakeCurrent(dpy, surface, surface, context); - eglQuerySurface(dpy, surface, EGL_WIDTH, &w); - eglQuerySurface(dpy, surface, EGL_HEIGHT, &h); - GLint dim = w<h ? w : h; - - glClear(GL_COLOR_BUFFER_BIT); - - GLint crop[4] = { 0, 4, 4, -4 }; - glBindTexture(GL_TEXTURE_2D, 0); - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glEnable(GL_TEXTURE_2D); - glColor4f(1,1,1,1); - - // packing is always 4 - uint8_t t8[] = { - 0x00, 0x55, 0x00, 0x55, - 0xAA, 0xFF, 0xAA, 0xFF, - 0x00, 0x55, 0x00, 0x55, - 0xAA, 0xFF, 0xAA, 0xFF }; - - uint16_t t16[] = { - 0x0000, 0x5555, 0x0000, 0x5555, - 0xAAAA, 0xFFFF, 0xAAAA, 0xFFFF, - 0x0000, 0x5555, 0x0000, 0x5555, - 0xAAAA, 0xFFFF, 0xAAAA, 0xFFFF }; - - uint16_t t5551[] = { - 0x0000, 0xFFFF, 0x0000, 0xFFFF, - 0xFFFF, 0x0000, 0xFFFF, 0x0000, - 0x0000, 0xFFFF, 0x0000, 0xFFFF, - 0xFFFF, 0x0000, 0xFFFF, 0x0000 }; - - uint32_t t32[] = { - 0xFF000000, 0xFF0000FF, 0xFF00FF00, 0xFFFF0000, - 0xFF00FF00, 0xFFFF0000, 0xFF000000, 0xFF0000FF, - 0xFF00FFFF, 0xFF00FF00, 0x00FF00FF, 0xFFFFFF00, - 0xFF000000, 0xFFFF00FF, 0xFF00FFFF, 0xFFFFFFFF - }; - - switch(test) - { - case 1: - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, - 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, t8); - break; - case 2: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - 4, 4, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, t16); - break; - case 3: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, t16); - break; - case 4: - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, - 4, 4, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, t16); - break; - case 5: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, t5551); - break; - case 6: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, - 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, t32); - break; - } - - glDrawTexiOES(0, 0, 0, dim, dim); - - eglSwapBuffers(dpy, surface); - return 0; -} diff --git a/opengl/tests/textures/Android.mk b/opengl/tests/textures/Android.mk index b0c9021327..a8c6220926 100644 --- a/opengl/tests/textures/Android.mk +++ b/opengl/tests/textures/Android.mk @@ -6,7 +6,8 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils \ - libGLES_CM \ + libEGL \ + libGLESv1_CM \ libui LOCAL_MODULE:= test-opengl-textures diff --git a/opengl/tests/textures/textures.c b/opengl/tests/textures/textures.c index 98e3be1440..214291b3b1 100644 --- a/opengl/tests/textures/textures.c +++ b/opengl/tests/textures/textures.c @@ -18,7 +18,9 @@ #include <stdlib.h> #include <stdio.h> -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <GLES/gl.h> +#include <GLES/glext.h> int main(int argc, char** argv) { diff --git a/opengl/tests/tritex/Android.mk b/opengl/tests/tritex/Android.mk index 4edac4cb4f..5cd1f048a3 100644 --- a/opengl/tests/tritex/Android.mk +++ b/opengl/tests/tritex/Android.mk @@ -6,7 +6,8 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libcutils \ - libGLES_CM \ + libEGL \ + libGLESv1_CM \ libui LOCAL_MODULE:= test-opengl-tritex diff --git a/opengl/tests/tritex/tritex.c b/opengl/tests/tritex/tritex.c index 8ebe7d4d72..60a7feb9b8 100644 --- a/opengl/tests/tritex/tritex.c +++ b/opengl/tests/tritex/tritex.c @@ -4,7 +4,9 @@ // // Ported from a Java version by Google. -#include <GLES/egl.h>
+#include <EGL/egl.h>
+#include <GLES/gl.h> + #include <stdio.h>
#include <stdlib.h> #include <math.h> diff --git a/services/Android.mk b/services/Android.mk deleted file mode 100644 index 5e912d6f3f..0000000000 --- a/services/Android.mk +++ /dev/null @@ -1,17 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -# the library -# ============================================================ -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := \ - $(call all-subdir-java-files) - -LOCAL_MODULE:= services - -LOCAL_JAVA_LIBRARIES := android.policy - -include $(BUILD_JAVA_LIBRARY) - -include $(BUILD_DROIDDOC) - |