Chromium Code Reviews| Index: example/SkiaSDLExample.cpp |
| diff --git a/example/SkiaSDLExample.cpp b/example/SkiaSDLExample.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5bd6aa08cd2d368e734c4872a2d91c0be2e18514 |
| --- /dev/null |
| +++ b/example/SkiaSDLExample.cpp |
| @@ -0,0 +1,266 @@ |
| +/* |
| + * Copyright 2015 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + * |
| + */ |
| + |
| +#include "GrContext.h" |
| +#include "SDL.h" |
| +#include "SkCanvas.h" |
| +#include "SkRandom.h" |
| +#include "SkSurface.h" |
| + |
| +#include "gl/GrGLInterface.h" |
| +#include "gl/GrGLUtil.h" |
| + |
| +#if defined(SK_BUILD_FOR_ANDROID) |
| +#include <GLES/gl.h> |
| +#elif defined(SK_BUILD_FOR_UNIX) |
| +#include <GL/gl.h> |
| +#elif defined(SK_BUILD_FOR_MAC) |
| +#include <gl.h> |
| +#endif |
| + |
|
robertphillips
2015/11/13 14:02:52
// This application is a simple example of how to
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| +struct ApplicationState { |
|
robertphillips
2015/11/13 14:02:51
// Storage for the user created rectangles. The la
joshualitt
2015/11/13 18:51:56
Acknowledged.
|
| + SkTArray<SkRect> fRects; |
| + bool fQuit; |
| +}; |
| + |
| +static void handle_error() { |
| + const char* error = SDL_GetError(); |
| + SkDebugf("SDL Error: %s\n", error); |
| + SDL_ClearError(); |
| +} |
| + |
| +static void handle_events(ApplicationState* state, SkCanvas* canvas) { |
| + SDL_Event event; |
| + while(SDL_PollEvent(&event)) { |
| + switch (event.type) { |
| + case SDL_MOUSEMOTION: |
| + if (event.motion.state == SDL_PRESSED) { |
|
robertphillips
2015/11/13 14:02:51
It might be clearer to make this "SkRect& rect ...
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + const SkRect& rect = state->fRects.back(); |
| + state->fRects.back() = SkRect::MakeLTRB(rect.fLeft, rect.fTop, |
| + event.motion.x, event.motion.y); |
| + } |
| + break; |
| + case SDL_MOUSEBUTTONDOWN: |
| + if (event.button.state == SDL_PRESSED) { |
| + state->fRects.push_back() = SkRect::MakeLTRB(SkIntToScalar(event.button.x), |
| + SkIntToScalar(event.button.y), |
| + SkIntToScalar(event.button.x), |
| + SkIntToScalar(event.button.y)); |
| + } |
| + break; |
| + case SDL_KEYDOWN: { |
| + SDL_Keycode key = event.key.keysym.sym; |
| + if (key == SDLK_ESCAPE) { |
| + state->fQuit = true; |
| + } |
| + break; |
| + } |
| + case SDL_QUIT: |
| + state->fQuit = true; |
| + break; |
| + default: |
| + break; |
| + } |
| + } |
| +} |
| + |
|
robertphillips
2015/11/13 14:02:51
// Create a pentagram
?
maybe rename the function
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| +static SkPath setup_concave_path() { |
|
robertphillips
2015/11/13 14:02:52
static const int kNumPoints = 5;
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + SkPath concavePath; |
| + SkPoint points[5] = {{0, SkIntToScalar(-50)} }; |
| + SkMatrix rot; |
| + rot.setRotate(SkIntToScalar(360) / 5); |
| + for (int i = 1; i < 5; ++i) { |
| + rot.mapPoints(points + i, points + i - 1, 1); |
| + } |
| + concavePath.moveTo(points[0]); |
|
robertphillips
2015/11/13 14:02:51
shouldn't this loop start at 1 ?
joshualitt
2015/11/13 18:51:55
dunno, it looks right. Why rock the boat? (Unles
robertphillips
2015/11/13 19:02:59
Don't we do a moveTo followed by a lineTo to the s
|
| + for (int i = 0; i < 5; ++i) { |
| + concavePath.lineTo(points[(2 * i) % 5]); |
| + } |
|
robertphillips
2015/11/13 14:02:51
concavePath.close() ?
joshualitt
2015/11/13 18:51:54
Acknowledged.
|
| + concavePath.setFillType(SkPath::kEvenOdd_FillType); |
| + SkASSERT(!concavePath.isConvex()); |
| + return concavePath; |
| +} |
| + |
| +/* |
| + * In this example, we use Skia with SDL. |
| + */ |
| +#if defined(SK_BUILD_FOR_ANDROID) |
| +int SDL_main(int argc, char** argv) { |
| +#else |
| +int main(int argc, char** argv) { |
| +#endif |
| + uint32_t windowFlags = 0; |
| + SDL_Window* window = nullptr; |
| +#if SK_SUPPORT_GPU |
| + SDL_GLContext glContext = nullptr; |
| +#if defined(SK_BUILD_FOR_ANDROID) |
|
robertphillips
2015/11/13 14:02:51
Can we pull out the two shared lines ?
// For And
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); |
| + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); |
| + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); |
| + windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | |
| + SDL_WINDOW_BORDERLESS | SDL_WINDOW_FULLSCREEN_DESKTOP | |
| + SDL_WINDOW_ALLOW_HIGHDPI; |
| +#else |
| + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); |
| + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); |
|
robertphillips
2015/11/13 14:02:52
// For all other clients we use the core profile a
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); |
| + |
| + windowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; |
| +#endif |
|
robertphillips
2015/11/13 14:02:51
Why not 8 ?
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); |
| + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); |
| + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); |
| + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); |
|
robertphillips
2015/11/13 14:02:52
Can we set depth to 0 ?
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); |
|
robertphillips
2015/11/13 14:02:51
// Skia needs 8 stencil bits
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); |
| + |
| + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); |
| +#endif // SK_SUPPORT_GPU |
| + |
|
robertphillips
2015/11/13 14:02:51
put this in the SK_SUPPORT_GPU block ?
where is m
joshualitt
2015/11/13 18:51:55
I setup the static variable, but got rid of the SK
|
| + // If you want multisampling, uncomment the below lines |
| + // SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); |
| + // SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaaSampleCount); |
| + |
| + /* |
| + * In a real application you might want to initialize more subsystems |
| + */ |
| + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { |
| + handle_error(); |
| + return 1; |
| + } |
| + |
| + // Setup window |
| + // This code will create a window with the same resolution as the user's desktop. |
| + SDL_DisplayMode dm; |
| + if (SDL_GetDesktopDisplayMode(0, &dm) != 0) { |
| + handle_error(); |
| + return 1; |
| + } |
| + |
|
robertphillips
2015/11/13 14:02:51
rm this ?
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + SkDebugf("Desktop display mode is %dx%d\n", dm.w, dm.h); |
| + |
|
robertphillips
2015/11/13 14:02:51
Add "SDL_Window*" here and remove the above declar
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + window = SDL_CreateWindow("Skia + SDL Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, |
| + dm.w, dm.h, windowFlags); |
| + |
| + if (!window) { |
| + handle_error(); |
| + return 1; |
| + } |
| + |
| + // To go fullscreen |
| + // SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN); |
| + |
| + // try and setup a GL context |
| + glContext = SDL_GL_CreateContext(window); |
| + if (!glContext) { |
| + handle_error(); |
| + return 1; |
| + } |
| + |
| + int success = SDL_GL_MakeCurrent(window, glContext); |
| + if (success != 0) { |
| + handle_error(); |
| + return success; |
| + } |
| + |
| + glViewport(0, 0, dm.w, dm.h); |
| + glClearColor(1, 1, 1, 1); |
| + glClearStencil(0); |
| + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); |
| + |
| + // setup GrContext |
| + SkAutoTUnref<const GrGLInterface> interface(GrGLCreateNativeInterface()); |
| + |
|
robertphillips
2015/11/13 14:02:51
uncomment this -> comment this out ?
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + // To use NVPR, uncomment this |
| + interface.reset(GrGLInterfaceRemoveNVPR(interface)); |
| + SkASSERT(interface); |
| + |
| + // setup contexts |
| + SkAutoTUnref<GrContext> grContext(GrContext::Create(kOpenGL_GrBackend, |
| + (GrBackendContext)interface.get())); |
| + SkASSERT(grContext); |
| + |
|
robertphillips
2015/11/13 14:02:51
// Wrap the frame buffer object attached to the sc
joshualitt
2015/11/13 18:51:55
Then its just a function which takes 10 arguments.
|
| + // setup rendertarget |
| + GrBackendRenderTargetDesc desc; |
| + desc.fWidth = dm.w; |
| + desc.fHeight = dm.h; |
| + desc.fConfig = kSkia8888_GrPixelConfig; |
| + desc.fOrigin = kBottomLeft_GrSurfaceOrigin; |
|
robertphillips
2015/11/13 14:02:52
kMSAASampleCount ?
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + desc.fSampleCnt = 0; // This would have to change for MSAA |
| + desc.fStencilBits = 8; |
| + GrGLint buffer; |
| + GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer); |
| + desc.fRenderTargetHandle = buffer; |
| + SkAutoTUnref<GrRenderTarget> |
| + renderTarget(grContext->textureProvider()->wrapBackendRenderTarget(desc)); |
| + |
| + // setup SkSurface |
| + // To use distance field text, use commented out SkSurfaceProps instead |
| + // SkSurfaceProps props(SkSurfaceProps::kUseDeviceIndependentFonts_Flag, |
| + // SkSurfaceProps::kLegacyFontHost_InitType); |
| + SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); |
| + SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTargetDirect(renderTarget, &props)); |
| + |
| + SkCanvas* canvas = surface->getCanvas(); |
| + |
| + ApplicationState state; |
| + sk_bzero(&state, sizeof(ApplicationState)); |
| + |
| + const char* helpMessage = "Click and drag to create rects. Press esc to quit."; |
| + |
| + SkPaint paint; |
| + |
|
robertphillips
2015/11/13 14:02:52
Can this be "SkImage* make_a_raster_image()" ?
joshualitt
2015/11/13 18:51:55
see my response to wrap_fbo_for_skia.
|
| + // create a surface for CPU rasterization |
|
robertphillips
2015/11/13 14:02:52
offscreenInfo seem unused
joshualitt
2015/11/13 18:51:55
Acknowledged.
|
| + SkImageInfo offscreenInfo = canvas->imageInfo(); |
| + offscreenInfo.makeWH(2000, 2000); |
|
robertphillips
2015/11/13 14:02:51
That's a big hunk o' memory
Can it just be the siz
joshualitt
2015/11/13 18:51:54
Acknowledged.
|
| + SkAutoTUnref<SkSurface> cpuSurface(SkSurface::NewRasterN32Premul(5000, 5000)); |
| + |
| + SkCanvas* offscreen = cpuSurface->getCanvas(); |
| + offscreen->save(); |
| + offscreen->translate(50.0f, 50.0f); |
| + offscreen->drawPath(setup_concave_path(), paint); |
| + offscreen->restore(); |
| + |
| + SkAutoTUnref<SkImage> image(cpuSurface->newImageSnapshot()); |
| + |
| + int rotation = 0; |
| + while (!state.fQuit) { // Our application loop |
| + SkRandom rand; |
| + canvas->clear(SK_ColorWHITE); |
| + handle_events(&state, canvas); |
| + |
| + paint.setColor(SK_ColorBLACK); |
| + canvas->drawText(helpMessage, strlen(helpMessage), SkIntToScalar(100), |
| + SkIntToScalar(100), paint); |
| + for (int i = 0; i < state.fRects.count(); i++) { |
| + paint.setColor(rand.nextU() | 0x44808080); |
| + canvas->drawRect(state.fRects[i], paint); |
| + } |
| + |
| + // draw offscreen canvas |
| + canvas->save(); |
| + canvas->translate(dm.w / 2.0, dm.h / 2.0); |
| + canvas->rotate(rotation++); |
| + canvas->drawImage(image, -50.0f, -50.0f); |
| + canvas->restore(); |
| + |
| + canvas->flush(); |
| + SDL_GL_SwapWindow(window); |
| + } |
| + |
| + if (glContext) { |
| + SDL_GL_DeleteContext(glContext); |
| + } |
| + |
| + //Destroy window |
| + SDL_DestroyWindow(window); |
| + |
| + //Quit SDL subsystems |
| + SDL_Quit(); |
| + return 0; |
| +} |