blob: ba8506c980c35415d75deae81f5c65c00f5d0312 [file] [log] [blame]
/*
* Copyright 2013 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkGLContext_DEFINED
#define SkGLContext_DEFINED
#include "GrGLInterface.h"
#include "../private/SkGpuFenceSync.h"
/**
* Create an offscreen opengl context with an RGBA8 / 8bit stencil FBO.
* Provides a GrGLInterface struct of function pointers for the context.
*/
class SK_API SkGLContext : public SkRefCnt {
public:
~SkGLContext() override;
bool isValid() const { return NULL != gl(); }
const GrGLInterface* gl() const { return fGL.get(); }
bool fenceSyncSupport() const { return SkToBool(fFenceSync); }
bool getMaxGpuFrameLag(int* maxFrameLag) const {
if (!fFenceSync) {
return false;
}
*maxFrameLag = kMaxFrameLag;
return true;
}
void makeCurrent() const;
/**
* The only purpose of this function it to provide a means of scheduling
* work on the GPU (since all of the subclasses create primary buffers for
* testing that are small and not meant to be rendered to the screen).
*
* If the platform supports fence sync (OpenGL 3.2+ or EGL_KHR_fence_sync),
* this will not swap any buffers, but rather emulate triple buffer
* synchronization using fences.
*
* Otherwise it will call the platform SwapBuffers method. This may or may
* not perform some sort of synchronization, depending on whether the
* drawing surface provided by the platform is double buffered.
*/
void swapBuffers();
/**
* This notifies the context that we are deliberately testing abandoning
* the context. It is useful for debugging contexts that would otherwise
* test that GPU resources are properly deleted. It also allows a debugging
* context to test that further GL calls are not made by Skia GPU code.
*/
void testAbandon();
class GLFenceSync; // SkGpuFenceSync implementation that uses the OpenGL functionality.
protected:
SkGLContext();
/*
* Methods that sublcasses must call from their constructors and destructors.
*/
void init(const GrGLInterface*, SkGpuFenceSync* = NULL);
void teardown();
/*
* Operations that have a platform-dependent implementation.
*/
virtual void onPlatformMakeCurrent() const = 0;
virtual void onPlatformSwapBuffers() const = 0;
virtual GrGLFuncPtr onPlatformGetProcAddress(const char*) const = 0;
private:
enum { kMaxFrameLag = 3 };
SkAutoTDelete<SkGpuFenceSync> fFenceSync;
SkPlatformGpuFence fFrameFences[kMaxFrameLag - 1];
int fCurrentFenceIdx;
/** Subclass provides the gl interface object if construction was
* successful. */
SkAutoTUnref<const GrGLInterface> fGL;
friend class GLFenceSync; // For onPlatformGetProcAddress.
typedef SkRefCnt INHERITED;
};
/** Creates platform-dependent GL context object
* Returns a valid gl context object or NULL if such can not be created.
* Note: If Skia embedder needs a custom GL context that sets up the GL
* interface, this function should be implemented by the embedder.
* Otherwise, the default implementation for the platform should be compiled in
* the library.
*/
SK_API SkGLContext* SkCreatePlatformGLContext(GrGLStandard forcedGpuAPI);
/**
* Helper macros for using the GL context through the GrGLInterface. Example:
* SK_GL(glCtx, GenTextures(1, &texID));
*/
#define SK_GL(ctx, X) (ctx).gl()->fFunctions.f ## X; \
SkASSERT(0 == (ctx).gl()->fFunctions.fGetError())
#define SK_GL_RET(ctx, RET, X) (RET) = (ctx).gl()->fFunctions.f ## X; \
SkASSERT(0 == (ctx).gl()->fFunctions.fGetError())
#define SK_GL_NOERRCHECK(ctx, X) (ctx).gl()->fFunctions.f ## X
#define SK_GL_RET_NOERRCHECK(ctx, RET, X) (RET) = (ctx).gl()->fFunctions.f ## X
#endif