static int host1x_gr3d_test(struct host1x_gr3d *gr3d) { struct host1x_syncpt *syncpt = &gr3d->client->syncpts[0]; struct host1x_pushbuf *pb; struct host1x_job *job; uint32_t fence; int err = 0; job = host1x_job_create(syncpt->id, 1); if (!job) return -ENOMEM; pb = host1x_job_append(job, gr3d->commands, 0); if (!pb) { host1x_job_free(job); return -ENOMEM; } host1x_pushbuf_push(pb, HOST1X_OPCODE_SETCL(0x000, 0x060, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x0001)); host1x_pushbuf_push(pb, 0x000001 << 8 | syncpt->id); err = host1x_client_submit(gr3d->client, job); if (err < 0) { host1x_job_free(job); return err; } host1x_job_free(job); err = host1x_client_flush(gr3d->client, &fence); if (err < 0) return err; err = host1x_client_wait(gr3d->client, fence, -1); if (err < 0) return err; return 0; }
static int host1x_gr3d_test(struct host1x_gr3d *gr3d) { struct host1x_syncpt *syncpt = &gr3d->client->syncpts[0]; struct host1x_pushbuf *pb; struct host1x_job *job; uint32_t fence; int err = 0; job = HOST1X_JOB_CREATE(syncpt->id, 1); if (!job) return -ENOMEM; pb = HOST1X_JOB_APPEND(job, gr3d->commands, 0); if (!pb) { host1x_job_free(job); return -ENOMEM; } host1x_pushbuf_push(pb, HOST1X_OPCODE_SETCL(0x000, 0x060, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x0001)); host1x_pushbuf_push(pb, 0x000001 << 8 | syncpt->id); err = HOST1X_CLIENT_SUBMIT(gr3d->client, job); if (err < 0) { host1x_job_free(job); return err; } host1x_job_free(job); err = HOST1X_CLIENT_FLUSH(gr3d->client, &fence); if (err < 0) return err; err = HOST1X_CLIENT_WAIT(gr3d->client, fence, ~0u); if (err < 0) return err; return 0; }
int host1x_gr3d_triangle(struct host1x_gr3d *gr3d, struct host1x_framebuffer *fb) { union { uint32_t u; float f; } value; struct host1x_syncpt *syncpt = &gr3d->client->syncpts[0]; float *attr = gr3d->attributes->ptr; struct host1x_pushbuf *pb; unsigned int depth = 32; struct host1x_job *job; uint32_t format, pitch; uint16_t *indices; uint32_t fence; int err, i; /* XXX: count syncpoint increments in command stream */ job = host1x_job_create(syncpt->id, 9); if (!job) return -ENOMEM; /* colors */ /* red */ *attr++ = 1.0f; *attr++ = 0.0f; *attr++ = 0.0f; *attr++ = 1.0f; /* green */ *attr++ = 0.0f; *attr++ = 1.0f; *attr++ = 0.0f; *attr++ = 1.0f; /* blue */ *attr++ = 0.0f; *attr++ = 0.0f; *attr++ = 1.0f; *attr++ = 1.0f; /* geometry */ *attr++ = 0.0f; *attr++ = 0.5f; *attr++ = 0.0f; *attr++ = 1.0f; *attr++ = -0.5f; *attr++ = -0.5f; *attr++ = 0.0f; *attr++ = 1.0f; *attr++ = 0.5f; *attr++ = -0.5f; *attr++ = 0.0f; *attr++ = 1.0f; indices = gr3d->attributes->ptr + host1x_bo_get_offset(gr3d->attributes, attr); /* indices */ *indices++ = 0x0000; *indices++ = 0x0001; *indices++ = 0x0002; err = host1x_bo_invalidate(gr3d->attributes, 0, 112); if (err < 0) { host1x_job_free(job); return err; } /* Command Buffer: mem: e462a7c0, offset: 3b4c, words: 103 commands: 103 */ pb = host1x_job_append(job, gr3d->commands, 0); if (!pb) { host1x_job_free(job); return -ENOMEM; } host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x404, 2)); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, 0x000fffff); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x354, 9)); host1x_pushbuf_push(pb, 0x3efffff0); host1x_pushbuf_push(pb, 0x3efffff0); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0x740, 0x035)); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xe26, 0x779)); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x346, 0x2)); host1x_pushbuf_push(pb, 0x00001401); host1x_pushbuf_push(pb, 0x3f800000); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x34c, 0x2)); host1x_pushbuf_push(pb, 0x00000002); host1x_pushbuf_push(pb, 0x3f000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x1)); host1x_pushbuf_push(pb, 0x000002 << 8 | syncpt->id); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x1)); host1x_pushbuf_push(pb, 0x000002 << 8 | syncpt->id); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x352, 0x1b)); value.f = fb->width * 8.0f; host1x_pushbuf_push(pb, value.u); value.f = fb->height * 8.0f; host1x_pushbuf_push(pb, value.u); value.f = fb->width * 8.0f; host1x_pushbuf_push(pb, value.u); value.f = fb->height * 8.0f; host1x_pushbuf_push(pb, value.u); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x358, 0x03)); host1x_pushbuf_push(pb, 0x4376f000); host1x_pushbuf_push(pb, 0x4376f000); host1x_pushbuf_push(pb, 0x40dfae14); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x343, 0x01)); host1x_pushbuf_push(pb, 0xb8e00000); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x350, 0x02)); host1x_pushbuf_push(pb, fb->width & 0xffff); host1x_pushbuf_push(pb, fb->height & 0xffff); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xe11, 0x01)); if (depth == 16) { format = HOST1X_GR3D_FORMAT_RGB565; pitch = fb->width * 2; } else { format = HOST1X_GR3D_FORMAT_RGBA8888; pitch = fb->width * 4; } host1x_pushbuf_push(pb, 0x04000000 | (pitch << 8) | format << 2 | 0x1); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x903, 0x01)); host1x_pushbuf_push(pb, 0x00000002); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xe15, 0x07)); host1x_pushbuf_push(pb, 0x08000001); host1x_pushbuf_push(pb, 0x08000001); host1x_pushbuf_push(pb, 0x08000001); host1x_pushbuf_push(pb, 0x08000001); host1x_pushbuf_push(pb, 0x08000001); host1x_pushbuf_push(pb, 0x08000001); host1x_pushbuf_push(pb, 0x08000001); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xe10, 0x01)); host1x_pushbuf_push(pb, 0x0c000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xe13, 0x01)); host1x_pushbuf_push(pb, 0x0c000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xe12, 0x01)); host1x_pushbuf_push(pb, 0x0c000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x348, 0x04)); host1x_pushbuf_push(pb, 0x3f800000); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, 0x3f800000); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xe27, 0x01)); for (i = 0; i < 4; ++i) { host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xa02, 0x06)); host1x_pushbuf_push(pb, 0x000001ff); host1x_pushbuf_push(pb, 0x000001ff); host1x_pushbuf_push(pb, 0x000001ff); host1x_pushbuf_push(pb, 0x00000030); host1x_pushbuf_push(pb, 0x00000020); host1x_pushbuf_push(pb, 0x00000030); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xa00, 0xe00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xa08, 0x100)); } host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x01)); host1x_pushbuf_push(pb, 0x000002 << 8 | syncpt->id); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x01)); host1x_pushbuf_push(pb, 0x000002 << 8 | syncpt->id); /* Command Buffer: mem: e462ae40, offset: 0, words: 10 commands: 10 */ /* * This seems to write the following vertex shader: * * attribute vec4 position; * attribute vec4 color; * varying vec4 vcolor; * * void main() * { * gl_Position = position; * vcolor = color; * } * * Register 0x205 contains an ID, while register 0x206 is a FIFO that * is used to upload vertex program code. */ host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0x205, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x206, 0x08)); host1x_pushbuf_push(pb, 0x401f9c6c); host1x_pushbuf_push(pb, 0x0040000d); host1x_pushbuf_push(pb, 0x8106c083); host1x_pushbuf_push(pb, 0x6041ff80); host1x_pushbuf_push(pb, 0x401f9c6c); host1x_pushbuf_push(pb, 0x0040010d); host1x_pushbuf_push(pb, 0x8106c083); host1x_pushbuf_push(pb, 0x6041ff9d); /* Command Buffer: mem: e462a7c0, offset: 3ce8, words: 16 commands: 16 */ host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x343, 0x01)); host1x_pushbuf_push(pb, 0xb8e00000); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x300, 0x02)); host1x_pushbuf_push(pb, 0x00000008); host1x_pushbuf_push(pb, 0x0000fecd); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xe20, 0x01)); host1x_pushbuf_push(pb, 0x58000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0x503, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0x545, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xe22, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0x603, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0x803, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x520, 0x01)); host1x_pushbuf_push(pb, 0x20006001); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x546, 0x01)); host1x_pushbuf_push(pb, 0x00000040); /* Command Buffer: mem: e462aec0, offset: 10, words: 26 commands: 26 */ /* * This writes the fragment shader: * * precision mediump float; * varying vec4 vcolor; * * void main() * { * gl_FragColor = vcolor; * } */ host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x541, 0x01)); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x500, 0x01)); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x601, 0x01)); host1x_pushbuf_push(pb, 0x00000001); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x604, 0x02)); host1x_pushbuf_push(pb, 0x104e51ba); host1x_pushbuf_push(pb, 0x00408102); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x701, 0x01)); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x801, 0x01)); host1x_pushbuf_push(pb, 0x00000001); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x804, 0x08)); host1x_pushbuf_push(pb, 0x0001c0c0); host1x_pushbuf_push(pb, 0x3f41f200); host1x_pushbuf_push(pb, 0x0001a080); host1x_pushbuf_push(pb, 0x3f41f200); host1x_pushbuf_push(pb, 0x00014000); host1x_pushbuf_push(pb, 0x3f41f200); host1x_pushbuf_push(pb, 0x00012040); host1x_pushbuf_push(pb, 0x3f41f200); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x806, 0x01)); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x901, 0x01)); host1x_pushbuf_push(pb, 0x00028005); /* Command Buffer: mem: e462a7c0, offset: 3d28, words: 66 commands: 66 */ host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xa02, 0x06)); host1x_pushbuf_push(pb, 0x000001ff); host1x_pushbuf_push(pb, 0x000001ff); host1x_pushbuf_push(pb, 0x000001ff); host1x_pushbuf_push(pb, 0x00000030); host1x_pushbuf_push(pb, 0x00000020); host1x_pushbuf_push(pb, 0x00000030); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xa00, 0xe00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xa08, 0x100)); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0x40c, 0x06)); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x120, 0x01)); host1x_pushbuf_push(pb, 0x00030081); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x344, 0x02)); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x01)); host1x_pushbuf_push(pb, 0x000001 << 8 | syncpt->id); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xa00, 0xe01)); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x00, 0x01)); host1x_pushbuf_push(pb, 0x000002 << 8 | syncpt->id); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xe01, 0x01)); /* relocate color render target */ host1x_pushbuf_relocate(pb, fb->bo, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0xe31, 0x01)); host1x_pushbuf_push(pb, 0x00000000); /* vertex position attribute */ host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x100, 0x01)); host1x_pushbuf_relocate(pb, gr3d->attributes, 0x30, 0); host1x_pushbuf_push(pb, 0xdeadbeef); /* vertex color attribute */ host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x102, 0x01)); host1x_pushbuf_relocate(pb, gr3d->attributes, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); /* primitive indices */ host1x_pushbuf_push(pb, HOST1X_OPCODE_INCR(0x121, 0x03)); host1x_pushbuf_relocate(pb, gr3d->attributes, 0x60, 0); host1x_pushbuf_push(pb, 0xdeadbeef); host1x_pushbuf_push(pb, 0xec000000); host1x_pushbuf_push(pb, 0x00200000); host1x_pushbuf_push(pb, HOST1X_OPCODE_IMM(0xe27, 0x02)); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x01)); host1x_pushbuf_push(pb, 0x000002 << 8 | syncpt->id); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x01)); host1x_pushbuf_push(pb, 0x000001 << 8 | syncpt->id); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x00, 0x01)); host1x_pushbuf_push(pb, 0x000001 << 8 | syncpt->id); err = host1x_client_submit(gr3d->client, job); if (err < 0) { host1x_job_free(job); return err; } host1x_job_free(job); err = host1x_client_flush(gr3d->client, &fence); if (err < 0) return err; err = host1x_client_wait(gr3d->client, fence, -1); if (err < 0) return err; return 0; }
static int host1x_gr2d_reset(struct host1x_gr2d *gr2d) { struct host1x_syncpt *syncpt = &gr2d->client->syncpts[0]; struct host1x_pushbuf *pb; struct host1x_job *job; uint32_t fence; int err; job = host1x_job_create(syncpt->id, 1); if (!job) return -ENOMEM; pb = host1x_job_append(job, gr2d->commands, 0); if (!pb) { host1x_job_free(job); return -ENOMEM; } host1x_pushbuf_push(pb, HOST1X_OPCODE_SETCL(0x000, 0x051, 0x00)); host1x_pushbuf_push(pb, HOST1X_OPCODE_EXTEND(0x00, 0x00000002)); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x009, 0x0009)); host1x_pushbuf_push(pb, 0x00000038); host1x_pushbuf_push(pb, 0x00000001); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x01c, 0x000b)); host1x_pushbuf_push(pb, 0x00000808); host1x_pushbuf_push(pb, 0x00700000); host1x_pushbuf_push(pb, 0x18010000); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x02b, 0x0009)); host1x_pushbuf_relocate(pb, gr2d->scratch, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); host1x_pushbuf_push(pb, 0x00000020); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x031, 0x0005)); host1x_pushbuf_relocate(pb, gr2d->scratch, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); host1x_pushbuf_push(pb, 0x00000020); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x046, 0x000d)); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_relocate(pb, gr2d->scratch, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); host1x_pushbuf_relocate(pb, gr2d->scratch, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x011, 0x0003)); host1x_pushbuf_push(pb, 0x00001000); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x013, 0x0003)); host1x_pushbuf_push(pb, 0x00001000); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x015, 0x0007)); host1x_pushbuf_push(pb, 0x00080080); host1x_pushbuf_push(pb, 0x80000000); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x037, 0x0003)); host1x_pushbuf_push(pb, 0x00000001); host1x_pushbuf_push(pb, 0x00000001); host1x_pushbuf_push(pb, HOST1X_OPCODE_EXTEND(0x01, 0x00000002)); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 0x0001)); host1x_pushbuf_push(pb, 0x000001 << 8 | syncpt->id); err = host1x_client_submit(gr2d->client, job); if (err < 0) { host1x_job_free(job); return err; } host1x_job_free(job); err = host1x_client_flush(gr2d->client, &fence); if (err < 0) return err; err = host1x_client_wait(gr2d->client, fence, -1); if (err < 0) return err; return 0; }
int host1x_gr2d_blit(struct host1x_gr2d *gr2d, struct host1x_framebuffer *src, struct host1x_framebuffer *dst, unsigned int sx, unsigned int sy, unsigned int dx, unsigned int dy, unsigned int width, unsigned int height) { struct host1x_syncpt *syncpt = &gr2d->client->syncpts[0]; struct host1x_pushbuf *pb; struct host1x_job *job; uint32_t fence; int err; job = host1x_job_create(syncpt->id, 1); if (!job) return -ENOMEM; pb = host1x_job_append(job, gr2d->commands, 0); if (!pb) { host1x_job_free(job); return -ENOMEM; } host1x_pushbuf_push(pb, HOST1X_OPCODE_SETCL(0, 0x51, 0)); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x009, 0x9)); host1x_pushbuf_push(pb, 0x0000003a); /* trigger */ host1x_pushbuf_push(pb, 0x00000000); /* cmdsel */ host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x01e, 0x7)); host1x_pushbuf_push(pb, 0x00000000); /* controlsecond */ /* * [20:20] source color depth (0: mono, 1: same) * [17:16] destination color depth (0: 8 bpp, 1: 16 bpp, 2: 32 bpp) */ host1x_pushbuf_push(pb, 0x00120000); /* controlmain */ host1x_pushbuf_push(pb, 0x000000cc); /* ropfade */ host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x046, 1)); /* * [20:20] destination write tile mode (0: linear, 1: tiled) * [ 0: 0] tile mode Y/RGB (0: linear, 1: tiled) */ host1x_pushbuf_push(pb, 0x00100001); /* tilemode */ host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x02b, 0xe149)); host1x_pushbuf_relocate(pb, dst->bo, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); /* dstba */ host1x_pushbuf_push(pb, dst->pitch); /* dstst */ host1x_pushbuf_relocate(pb, src->bo, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); /* srcba */ host1x_pushbuf_push(pb, src->pitch); /* srcst */ host1x_pushbuf_push(pb, height << 16 | width); /* dstsize */ host1x_pushbuf_push(pb, sy << 16 | sx); /* srcps */ host1x_pushbuf_push(pb, dy << 16 | dx); /* dstps */ host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x000, 1)); host1x_pushbuf_push(pb, 0x000001 << 8 | syncpt->id); err = host1x_client_submit(gr2d->client, job); if (err < 0) { host1x_job_free(job); return err; } host1x_job_free(job); err = host1x_client_flush(gr2d->client, &fence); if (err < 0) return err; err = host1x_client_wait(gr2d->client, fence, -1); if (err < 0) return err; return 0; }
int host1x_gr2d_clear(struct host1x_gr2d *gr2d, struct host1x_framebuffer *fb, float red, float green, float blue, float alpha) { struct host1x_syncpt *syncpt = &gr2d->client->syncpts[0]; struct host1x_pushbuf *pb; struct host1x_job *job; uint32_t fence, color; uint32_t pitch; int err; if (fb->depth == 16) { color = ((uint32_t)(red * 31) << 11) | ((uint32_t)(green * 63) << 5) | ((uint32_t)(blue * 31) << 0); pitch = fb->width * 2; } else { color = ((uint32_t)(alpha * 255) << 24) | ((uint32_t)(blue * 255) << 16) | ((uint32_t)(green * 255) << 8) | ((uint32_t)(red * 255) << 0); pitch = fb->width * 4; } job = host1x_job_create(syncpt->id, 1); if (!job) return -ENOMEM; pb = host1x_job_append(job, gr2d->commands, 0); if (!pb) { host1x_job_free(job); return -ENOMEM; } host1x_pushbuf_push(pb, HOST1X_OPCODE_SETCL(0, 0x51, 0)); host1x_pushbuf_push(pb, HOST1X_OPCODE_EXTEND(0, 0x01)); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x09, 9)); host1x_pushbuf_push(pb, 0x0000003a); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x1e, 7)); host1x_pushbuf_push(pb, 0x00000000); if (fb->depth == 16) host1x_pushbuf_push(pb, 0x00010044); /* 16-bit depth */ else host1x_pushbuf_push(pb, 0x00020044); /* 32-bit depth */ host1x_pushbuf_push(pb, 0x000000cc); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x2b, 9)); host1x_pushbuf_relocate(pb, fb->bo, 0, 0); host1x_pushbuf_push(pb, 0xdeadbeef); host1x_pushbuf_push(pb, pitch); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x35, 1)); host1x_pushbuf_push(pb, color); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x46, 1)); host1x_pushbuf_push(pb, 0x00100000); host1x_pushbuf_push(pb, HOST1X_OPCODE_MASK(0x38, 5)); host1x_pushbuf_push(pb, fb->height << 16 | fb->width); host1x_pushbuf_push(pb, 0x00000000); host1x_pushbuf_push(pb, HOST1X_OPCODE_EXTEND(1, 1)); host1x_pushbuf_push(pb, HOST1X_OPCODE_NONINCR(0x00, 1)); host1x_pushbuf_push(pb, 0x000001 << 8 | syncpt->id); err = host1x_client_submit(gr2d->client, job); if (err < 0) { host1x_job_free(job); return err; } host1x_job_free(job); err = host1x_client_flush(gr2d->client, &fence); if (err < 0) return err; err = host1x_client_wait(gr2d->client, fence, -1); if (err < 0) return err; return 0; }