1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include <stdio.h>
9
10#include <GL/osmesa.h>
11
12#include "fiddle_main.h"
13
14// Globals externed in fiddle_main.h
15SkBitmap source;
16SkImage* image(nullptr);
17
18static void encode_to_base64(const void* data, size_t size, FILE* out) {
19    const uint8_t* input = reinterpret_cast<const uint8_t*>(data);
20    const uint8_t* end = &input[size];
21    static const char codes[] =
22            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
23            "abcdefghijklmnopqrstuvwxyz0123456789+/";
24    while (input != end) {
25        uint8_t b = (*input & 0xFC) >> 2;
26        fputc(codes[b], out);
27        b = (*input & 0x03) << 4;
28        ++input;
29        if (input == end) {
30            fputc(codes[b], out);
31            fputs("==", out);
32            return;
33        }
34        b |= (*input & 0xF0) >> 4;
35        fputc(codes[b], out);
36        b = (*input & 0x0F) << 2;
37        ++input;
38        if (input == end) {
39            fputc(codes[b], out);
40            fputc('=', out);
41            return;
42        }
43        b |= (*input & 0xC0) >> 6;
44        fputc(codes[b], out);
45        b = *input & 0x3F;
46        fputc(codes[b], out);
47        ++input;
48    }
49}
50
51static void dump_output(SkData* data, const char* name, bool last = true) {
52    if (data) {
53        printf("\t\"%s\": \"", name);
54        encode_to_base64(data->data(), data->size(), stdout);
55        fputs(last ? "\"\n" : "\",\n", stdout);
56    }
57}
58
59static SkData* encode_snapshot(SkSurface* surface) {
60    SkAutoTUnref<SkImage> img(surface->newImageSnapshot());
61    return img ? img->encode() : nullptr;
62}
63
64static OSMesaContext create_osmesa_context() {
65    OSMesaContext osMesaContext =
66        OSMesaCreateContextExt(OSMESA_BGRA, 0, 0, 0, nullptr);
67    if (osMesaContext != nullptr) {
68        static uint32_t buffer[16 * 16];
69        OSMesaMakeCurrent(osMesaContext, &buffer, GL_UNSIGNED_BYTE, 16, 16);
70    }
71    return osMesaContext;
72}
73
74static GrContext* create_mesa_grcontext() {
75    SkAutoTUnref<const GrGLInterface> mesa(GrGLCreateMesaInterface());
76    intptr_t backend = reinterpret_cast<intptr_t>(mesa.get());
77    return backend ? GrContext::Create(kOpenGL_GrBackend, backend) : nullptr;
78}
79
80
81int main() {
82    const DrawOptions options = GetDrawOptions();
83    fprintf(stderr, "%s\n", options.source);
84    if (options.source) {
85        SkAutoTUnref<SkData> data(SkData::NewFromFileName(options.source));
86        if (!data) {
87            perror(options.source);
88            return 1;
89        } else {
90            image = SkImage::NewFromEncoded(data);
91            if (!image) {
92                perror("Unable to decode the source image.");
93                return 1;
94            }
95            SkAssertResult(image->asLegacyBitmap(
96                                   &source, SkImage::kRO_LegacyBitmapMode));
97        }
98    }
99    SkAutoTUnref<SkData> rasterData, gpuData, pdfData, skpData;
100    if (options.raster) {
101        SkAutoTUnref<SkSurface> rasterSurface(
102                SkSurface::NewRaster(SkImageInfo::MakeN32Premul(options.size)));
103        draw(rasterSurface->getCanvas());
104        rasterData.reset(encode_snapshot(rasterSurface));
105    }
106    if (options.gpu) {
107        OSMesaContext osMesaContext = create_osmesa_context();
108        SkAutoTUnref<GrContext> grContext(create_mesa_grcontext());
109        if (!grContext) {
110            fputs("Unable to get Mesa GrContext.\n", stderr);
111        } else {
112            SkAutoTUnref<SkSurface> surface(
113                    SkSurface::NewRenderTarget(
114                            grContext,
115                            SkBudgeted::kNo,
116                            SkImageInfo::MakeN32Premul(options.size)));
117            if (!surface) {
118                fputs("Unable to get render surface.\n", stderr);
119                exit(1);
120            }
121            draw(surface->getCanvas());
122            gpuData.reset(encode_snapshot(surface));
123        }
124        if (osMesaContext) {
125            OSMesaDestroyContext(osMesaContext);
126        }
127    }
128    if (options.pdf) {
129        SkDynamicMemoryWStream pdfStream;
130        SkAutoTUnref<SkDocument> document(SkDocument::CreatePDF(&pdfStream));
131        draw(document->beginPage(options.size.width(), options.size.height()));
132        document->close();
133        pdfData.reset(pdfStream.copyToData());
134    }
135    if (options.skp) {
136        SkSize size;
137        size = options.size;
138        SkPictureRecorder recorder;
139        draw(recorder.beginRecording(size.width(), size.height()));
140        SkAutoTUnref<SkPicture> picture(recorder.endRecordingAsPicture());
141        SkDynamicMemoryWStream skpStream;
142        picture->serialize(&skpStream);
143        skpData.reset(skpStream.copyToData());
144    }
145
146    printf("{\n");
147    dump_output(rasterData, "Raster", !gpuData && !pdfData && !skpData);
148    dump_output(gpuData, "Gpu", !pdfData && !skpData);
149    dump_output(pdfData, "Pdf", !skpData);
150    dump_output(skpData, "Skp");
151    printf("}\n");
152
153    SkSafeSetNull(image);
154    return 0;
155}
156