enum piglit_result piglit_display() { bool pass = true; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); allocate_data_arrays(); draw_reference_image(false /* sample_alpha_to_coverage */, true /* sample_alpha_to_one */); draw_test_image(false /* sample_alpha_to_coverage */, true /* sample_alpha_to_one */); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); pass = piglit_probe_rect_halves_equal_rgba(0, 0, piglit_width, piglit_height) && pass; /* Free the memory allocated for data arrays */ free_data_arrays(); if (!piglit_automatic) piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
enum piglit_result piglit_display() { bool pass = true; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); allocate_data_arrays(); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC1_ALPHA); /* Reference image drawn when sample_alpha_to_coverage is enabled, * doesn't represent an expected image. Reference image is drawn only * to visualize the image difference caused by enabling * sample_alpha_to_coverage */ draw_reference_image(true /* sample_alpha_to_coverage */, false /* sample_alpha_to_one */); draw_test_image(true /* sample_alpha_to_coverage */, false /* sample_alpha_to_one */); glDisable(GL_BLEND); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; /* Probe test images of all the draw_buffers blitted to resolve fbo * and compare with expected color values. This method of verification * is appropriate for tests with sample-alpha-to-coverage enabled. * Possibility of dithering effect when the coverage value is not a * strict multiple of 1 / num_samples makes image compare (test / * reference image) unsuitable for this test. */ pass = probe_framebuffer_color() && pass; /* Free the memory allocated for data arrays */ free_data_arrays(); if (!piglit_automatic) piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
enum piglit_result piglit_display() { bool pass = true; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, piglit_winsys_fbo); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); allocate_data_arrays(); /* Set sample_alpha_to_one = false to generate the reference image */ draw_reference_image(false /* sample_alpha_to_coverage */, false /* sample_alpha_to_one */); /* Test multisample fbo with GL_SAMPLE_ALPHA_TO_ONE enabled but * GL_MULTISAMPLE disabled */ glDisable(GL_MULTISAMPLE); draw_test_image(false /* sample_alpha_to_coverage */, true /* sample_alpha_to_one */); glEnable(GL_MULTISAMPLE); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; glBindFramebuffer(GL_READ_FRAMEBUFFER, piglit_winsys_fbo); pass = piglit_probe_rect_halves_equal_rgba(0, 0, piglit_width, piglit_height) && pass; /* Free the memory allocated for data arrays */ free_data_arrays(); if (!piglit_automatic) piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
enum piglit_result piglit_display(void) { GLubyte *win_image, *fbo_image; GLuint fbo, rb; bool pass = true; win_image = (GLubyte *) malloc(piglit_width * piglit_height * 3); fbo_image = (GLubyte *) malloc(piglit_width * piglit_height * 3); glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); glGenRenderbuffers(1, &rb); glBindRenderbuffer(GL_RENDERBUFFER, rb); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, piglit_width, piglit_height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb); assert(glGetError() == 0); assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT); /* draw reference image in the window */ glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo); draw_test_image(); glReadPixels(0, 0, piglit_width, piglit_height, GL_RGB, GL_UNSIGNED_BYTE, win_image); /* draw test image in fbo */ glBindFramebuffer(GL_FRAMEBUFFER, fbo); glReadBuffer(GL_COLOR_ATTACHMENT0); draw_test_image(); glReadPixels(0, 0, piglit_width, piglit_height, GL_RGB, GL_UNSIGNED_BYTE, fbo_image); /* compare images */ if (memcmp(win_image, fbo_image, piglit_width * piglit_height * 3)) { #if 0 /* helpful debug code */ int i, k; for (i = k = 0; i < piglit_width * piglit_height * 3; i++) { if (win_image[i] != fbo_image[i] && k++ < 40) printf("%d: %d vs. %d\n", i, win_image[i], fbo_image[i]); } #endif printf("Image comparison failed!\n"); pass = false; } else if (!piglit_automatic) { printf("Image comparison passed.\n"); } glBindFramebuffer(GL_FRAMEBUFFER, piglit_winsys_fbo); #if 0 /* for debug/compare (alternate diplaying Window vs. FBO image) */ { int i; glWindowPos2i(0,0); for (i = 0; i < 10; i++) { GLubyte *image = (i & 1) ? fbo_image : win_image; printf("Showing %s image\n", (i & 1) ? "FBO" : "window"); glDrawPixels(piglit_width, piglit_height, GL_RGB, GL_UNSIGNED_BYTE, image); piglit_present_results(); sleep(1); } } #endif piglit_present_results(); glDeleteRenderbuffers(1, &rb); glDeleteFramebuffers(1, &fbo); free(win_image); free(fbo_image); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }
int main(int argc, char *argv[]) { uint64_t has_dumb; int ret, fd, opt, i; void *map; struct drm_mode_destroy_dumb dreq; struct drm_mode_create_dumb creq; struct drm_mode_map_dumb mreq; drmModePlaneRes *resources; drmModePlane *plane = NULL; uint32_t handle, stride, size; uint32_t plane_id, crtc_id; uint32_t width, height; uint32_t posx, posy; uint32_t fb; /* parse command line */ while ((opt = getopt(argc, argv, "x:y:w:v:c:p:h")) != -1) { switch (opt) { case 'x': posx = atoi(optarg); break; case 'y': posy = atoi(optarg); break; case 'w': width = atoi(optarg); break; case 'v': height = atoi(optarg); break; case 'p': plane_id = atoi(optarg); break; case 'c': crtc_id = atoi(optarg); break; case 'h': default: printf("usage: -h] -c <connector> -e <encoder> -m <mode>\n"); printf("\t-h: this help message\n"); printf("\t-c <crtc> crtc id, default is 0\n"); printf("\t-p <plane> plane id, default is 0\n"); printf("\t-x <posx> plane top left corner xpos, default is 0'\n"); printf("\t-y <posy> plane top left corner ypos, default is 0'\n"); printf("\t-w <width> plane width, default is 0'\n"); printf("\t-v <height> plane height, default is 0'\n"); exit(0); } } /* open drm device */ fd = open(device_name, O_RDWR | O_CLOEXEC); if (fd < 0) { perror("cannot open drm device"); exit(-1); } drmSetMaster(fd); /* check dumb buffer support */ if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0) { perror("DRM_CAP_DUMB_BUFFER ioctl"); ret = -EFAULT; goto err_close; } if (!has_dumb) { fprintf(stderr, "driver does not support dumb buffers\n"); ret = -EFAULT; goto err_close; } /* get plane */ resources = drmModeGetPlaneResources(fd); if (!resources || resources->count_planes == 0) { fprintf(stderr, "drmModeGetPlaneResources failed\n"); ret = -ENODEV; goto err_close; } for (i = 0; i < resources->count_planes; i++) { drmModePlane *p = drmModeGetPlane(fd, resources->planes[i]); if (!p) continue; if (p->plane_id == plane_id) { plane = p; break; } drmModeFreePlane(plane); } if (!plane) { fprintf(stderr, "couldn't find specified plane\n"); ret = -ENODEV; goto err_close; } /* create dumb buffer object */ memset(&creq, 0, sizeof(creq)); creq.height = height; creq.width = width; creq.bpp = 32; ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); if (ret) { fprintf(stderr, "failed drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB)\n"); goto err_close; } handle = creq.handle; stride = creq.pitch; size = creq.size; /* create framebuffer for dumb buffer object */ ret = drmModeAddFB(fd, width, height, 24, 32, stride, handle, &fb); if (ret) { fprintf(stderr, "cannot add drm framebuffer for dumb buffer object\n"); goto err_destroy_dumb; } /* map dumb buffer object */ memset(&mreq, 0, sizeof(mreq)); mreq.handle = handle; ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); if (ret) { fprintf(stderr, "failed drmIoctl(DRM_IOCTL_MODE_MAP_DUMB)\n"); goto err_destroy_fb; } map = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mreq.offset); if (map == MAP_FAILED) { fprintf(stderr, "cannot mmap dumb buffer\n"); goto err_destroy_fb; } /* setup new plane */ ret = drmModeSetPlane(fd, plane_id, crtc_id, fb, 0, posx, posy, width, height, 0, 0, width << 16, height << 16); if (ret) { fprintf(stderr, "cannot set plane\n"); goto err_unmap; } /* draw on the screen */ draw_test_image((uint32_t *) map, width, height); getchar(); draw_fancy_image((uint32_t *) map, width, height); getchar(); drmModeSetPlane(fd, plane_id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); err_unmap: if (map) munmap(map, size); err_destroy_fb: drmModeRmFB(fd, fb); err_destroy_dumb: memset(&dreq, 0, sizeof(dreq)); dreq.handle = handle; ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq); if (ret) { fprintf(stderr, "cannot destroy dumb buffer\n"); } err_close: close(fd); return ret; }